From 66330a9d59d57c1454a8361cb01df3f88ed6d5e8 Mon Sep 17 00:00:00 2001 From: "ramil@mysql.com" <> Date: Fri, 24 Jun 2005 12:51:11 +0500 Subject: [PATCH 1/3] an improvement (bug #7851: C++ 'new' conflicts with kernel header asm/system.h). --- include/my_global.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/my_global.h b/include/my_global.h index f8ba555b150..9b53be66db0 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -274,10 +274,8 @@ C_MODE_START int __cxa_pure_virtual() {\ #include #endif #ifdef HAVE_ATOMIC_ADD -#if defined(__ia64__) #define new my_arg_new #define need_to_restore_new 1 -#endif C_MODE_START #include C_MODE_END From b0e6db14c54a621bfcfafb3a65d87124e43c47aa Mon Sep 17 00:00:00 2001 From: "ramil@mysql.com" <> Date: Fri, 24 Jun 2005 14:04:48 +0500 Subject: [PATCH 2/3] backport for #10568: Function 'LAST_DAY(date)' does not return NULL for invalid argument. --- mysql-test/r/func_time.result | 15 +++++++++++++++ mysql-test/t/func_time.test | 7 +++++++ sql/item_timefunc.cc | 2 +- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 4dd00ab74a1..fc872285acb 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -611,3 +611,18 @@ SELECT count(*) FROM t1 WHERE d>FROM_DAYS(TO_DAYS(@TMP)) AND d<=FROM_DAYS(TO_DAY count(*) 3 DROP TABLE t1; +select last_day('2005-00-00'); +last_day('2005-00-00') +NULL +Warnings: +Warning 1292 Truncated incorrect datetime value: '2005-00-00' +select last_day('2005-00-01'); +last_day('2005-00-01') +NULL +Warnings: +Warning 1292 Truncated incorrect datetime value: '2005-00-01' +select last_day('2005-01-00'); +last_day('2005-01-00') +NULL +Warnings: +Warning 1292 Truncated incorrect datetime value: '2005-01-00' diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index 0f495ef891d..9e2703da110 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -307,3 +307,10 @@ INSERT INTO t1 VALUES (NOW()); SELECT count(*) FROM t1 WHERE d>FROM_DAYS(TO_DAYS(@TMP)) AND d<=FROM_DAYS(TO_DAYS(@TMP)+1); DROP TABLE t1; +# +# Bug #10568 +# + +select last_day('2005-00-00'); +select last_day('2005-00-01'); +select last_day('2005-01-00'); diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index a3cf69035f3..0e1a8766e8f 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -2817,7 +2817,7 @@ String *Item_func_str_to_date::val_str(String *str) bool Item_func_last_day::get_date(TIME *ltime, uint fuzzy_date) { - if (get_arg0_date(ltime,fuzzy_date)) + if (get_arg0_date(ltime, fuzzy_date & ~TIME_FUZZY_DATE)) return 1; uint month_idx= ltime->month-1; ltime->day= days_in_month[month_idx]; From 2dcf451b81d8b11395f1abe02f00dae80eafea6a Mon Sep 17 00:00:00 2001 From: "ingo@mysql.com" <> Date: Fri, 24 Jun 2005 17:47:09 +0200 Subject: [PATCH 3/3] Bug#10178 - failure to find a row in heap table by concurrent UPDATEs Moved the key statistics update to info(). The table is not locked in open(). This made wrong stats possible. No test case for the test suite. This happens only with heavy concurrency. A test script is added to the bug report. --- mysql-test/r/heap_hash.result | 23 ++++++++++++----------- mysql-test/t/heap_hash.test | 2 ++ sql/ha_heap.cc | 31 ++++++++++++++++++++++++++----- sql/ha_heap.h | 4 +++- 4 files changed, 43 insertions(+), 17 deletions(-) diff --git a/mysql-test/r/heap_hash.result b/mysql-test/r/heap_hash.result index d3673cd2a63..e5098ab8c87 100644 --- a/mysql-test/r/heap_hash.result +++ b/mysql-test/r/heap_hash.result @@ -231,18 +231,19 @@ explain select * from t1 where a='aaad'; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ref a a 8 const 1 Using where insert into t1 select * from t1; +flush tables; explain select * from t1 where a='aaaa'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref a a 8 const 1 Using where +1 SIMPLE t1 ref a a 8 const 2 Using where explain select * from t1 where a='aaab'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref a a 8 const 1 Using where +1 SIMPLE t1 ref a a 8 const 2 Using where explain select * from t1 where a='aaac'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref a a 8 const 1 Using where +1 SIMPLE t1 ref a a 8 const 2 Using where explain select * from t1 where a='aaad'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref a a 8 const 1 Using where +1 SIMPLE t1 ref a a 8 const 2 Using where flush tables; explain select * from t1 where a='aaaa'; id select_type table type possible_keys key key_len ref rows Extra @@ -261,16 +262,16 @@ delete from t1; insert into t1 select * from t2; explain select * from t1 where a='aaaa'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref a a 8 const 1 Using where +1 SIMPLE t1 ref a a 8 const 2 Using where explain select * from t1 where a='aaab'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref a a 8 const 1 Using where +1 SIMPLE t1 ref a a 8 const 2 Using where explain select * from t1 where a='aaac'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref a a 8 const 1 Using where +1 SIMPLE t1 ref a a 8 const 2 Using where explain select * from t1 where a='aaad'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref a a 8 const 1 Using where +1 SIMPLE t1 ref a a 8 const 2 Using where drop table t1, t2; create table t1 ( id int unsigned not null primary key auto_increment, @@ -345,15 +346,15 @@ insert into t3 select name, name from t1; show index from t3; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment t3 1 a 1 a NULL NULL NULL NULL HASH -t3 1 a 2 b NULL 15 NULL NULL HASH +t3 1 a 2 b NULL 13 NULL NULL HASH show index from t3; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment t3 1 a 1 a NULL NULL NULL NULL HASH -t3 1 a 2 b NULL 15 NULL NULL HASH +t3 1 a 2 b NULL 13 NULL NULL HASH explain select * from t1 ignore key(btree_idx), t3 where t1.name='matt' and t3.a = concat('',t1.name) and t3.b=t1.name; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ref heap_idx heap_idx 20 const 7 Using where -1 SIMPLE t3 ref a a 40 func,const 6 Using where +1 SIMPLE t3 ref a a 40 func,const 7 Using where drop table t1, t2, t3; create temporary table t1 ( a int, index (a) ) engine=memory; insert into t1 values (1),(2),(3),(4),(5); diff --git a/mysql-test/t/heap_hash.test b/mysql-test/t/heap_hash.test index 6d27f19dfad..59af50da932 100644 --- a/mysql-test/t/heap_hash.test +++ b/mysql-test/t/heap_hash.test @@ -169,6 +169,8 @@ explain select * from t1 where a='aaac'; explain select * from t1 where a='aaad'; insert into t1 select * from t1; +# avoid statistics differences between normal and ps-protocol tests +flush tables; explain select * from t1 where a='aaaa'; explain select * from t1 where a='aaab'; explain select * from t1 where a='aaac'; diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc index 4fc0116a26a..f8c2e6cc338 100644 --- a/sql/ha_heap.cc +++ b/sql/ha_heap.cc @@ -60,7 +60,15 @@ int ha_heap::open(const char *name, int mode, uint test_if_locked) { /* Initialize variables for the opened table */ set_keys_for_scanning(); - update_key_stats(); + /* + We cannot run update_key_stats() here because we do not have a + lock on the table. The 'records' count might just be changed + temporarily at this moment and we might get wrong statistics (Bug + #10178). Instead we request for update. This will be done in + ha_heap::info(), which is always called before key statistics are + used. + */ + key_stats_ok= FALSE; } return (file ? 0 : 1); } @@ -112,6 +120,8 @@ void ha_heap::update_key_stats() } } records_changed= 0; + /* At the end of update_key_stats() we can proudly claim they are OK. */ + key_stats_ok= TRUE; } int ha_heap::write_row(byte * buf) @@ -125,7 +135,7 @@ int ha_heap::write_row(byte * buf) res= heap_write(file,buf); if (!res && ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records) - update_key_stats(); + key_stats_ok= FALSE; return res; } @@ -138,7 +148,7 @@ int ha_heap::update_row(const byte * old_data, byte * new_data) res= heap_update(file,old_data,new_data); if (!res && ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records) - update_key_stats(); + key_stats_ok= FALSE; return res; } @@ -149,7 +159,7 @@ int ha_heap::delete_row(const byte * buf) res= heap_delete(file,buf); if (!res && table->tmp_table == NO_TMP_TABLE && ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records) - update_key_stats(); + key_stats_ok= FALSE; return res; } @@ -262,6 +272,13 @@ void ha_heap::info(uint flag) delete_length= info.deleted * info.reclength; if (flag & HA_STATUS_AUTO) auto_increment_value= info.auto_increment; + /* + If info() is called for the first time after open(), we will still + have to update the key statistics. Hoping that a table lock is now + in place. + */ + if (! key_stats_ok) + update_key_stats(); } int ha_heap::extra(enum ha_extra_function operation) @@ -273,7 +290,7 @@ int ha_heap::delete_all_rows() { heap_clear(file); if (table->tmp_table == NO_TMP_TABLE) - update_key_stats(); + key_stats_ok= FALSE; return 0; } @@ -433,7 +450,11 @@ ha_rows ha_heap::records_in_range(uint inx, key_range *min_key, max_key->flag != HA_READ_AFTER_KEY) return HA_POS_ERROR; // Can only use exact keys else + { + /* Assert that info() did run. We need current statistics here. */ + DBUG_ASSERT(key_stats_ok); return key->rec_per_key[key->key_parts-1]; + } } diff --git a/sql/ha_heap.h b/sql/ha_heap.h index 33de0156074..cbe2474492d 100644 --- a/sql/ha_heap.h +++ b/sql/ha_heap.h @@ -29,8 +29,10 @@ class ha_heap: public handler key_map btree_keys; /* number of records changed since last statistics update */ uint records_changed; + bool key_stats_ok; public: - ha_heap(TABLE *table): handler(table), file(0), records_changed(0) {} + ha_heap(TABLE *table): handler(table), file(0), records_changed(0), + key_stats_ok(0) {} ~ha_heap() {} const char *table_type() const { return "HEAP"; } const char *index_type(uint inx)