From 8bba9089150dfdb82daaa50147f9d58d1d8956a9 Mon Sep 17 00:00:00 2001 From: "sergefp@mysql.com" <> Date: Fri, 13 Jul 2007 19:13:40 +0400 Subject: BUG#29740: Wrong query results for index_merge/union over HEAP table. - return HA_KEY_SCAN_NOT_ROR flag for HASH indexes; - Fix ha_heap::cmp_ref() to work with BTREE index scans. --- mysql-test/r/index_merge.result | 61 +++++++++++++++++++++++++++++++++++++++++ mysql-test/t/index_merge.test | 43 +++++++++++++++++++++++++++++ sql/ha_heap.h | 8 ++---- sql/opt_range.cc | 25 ++++++++--------- 4 files changed, 118 insertions(+), 19 deletions(-) diff --git a/mysql-test/r/index_merge.result b/mysql-test/r/index_merge.result index 9456b4ec978..c7e4ead9eeb 100644 --- a/mysql-test/r/index_merge.result +++ b/mysql-test/r/index_merge.result @@ -455,3 +455,64 @@ a 1 UNLOCK TABLES; DROP TABLE t1, t2; +CREATE TABLE `t1` ( +`a` int(11) DEFAULT NULL, +`filler` char(200) DEFAULT NULL, +`b` int(11) DEFAULT NULL, +KEY `a` (`a`), +KEY `b` (`b`) +) ENGINE=MEMORY DEFAULT CHARSET=latin1; +insert into t1 values +(0, 'filler', 0), (1, 'filler', 1), (2, 'filler', 2), (3, 'filler', 3), +(4, 'filler', 4), (5, 'filler', 5), (6, 'filler', 6), (7, 'filler', 7), +(8, 'filler', 8), (9, 'filler', 9), (0, 'filler', 0), (1, 'filler', 1), +(2, 'filler', 2), (3, 'filler', 3), (4, 'filler', 4), (5, 'filler', 5), +(6, 'filler', 6), (7, 'filler', 7), (8, 'filler', 8), (9, 'filler', 9), +(10, 'filler', 10), (11, 'filler', 11), (12, 'filler', 12), (13, 'filler', 13), +(14, 'filler', 14), (15, 'filler', 15), (16, 'filler', 16), (17, 'filler', 17), +(18, 'filler', 18), (19, 'filler', 19), (4, '5 ', 0), (5, '4 ', 0), +(4, '4 ', 0), (4, 'qq ', 5), (5, 'qq ', 4), (4, 'zz ', 4); +create table t2( +`a` int(11) DEFAULT NULL, +`filler` char(200) DEFAULT NULL, +`b` int(11) DEFAULT NULL, +KEY USING BTREE (`a`), +KEY USING BTREE (`b`) +) ENGINE=MEMORY DEFAULT CHARSET=latin1; +insert into t2 select * from t1; +must use sort-union rather than union: +explain select * from t1 where a=4 or b=4; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index_merge a,b a,b 5,5 NULL 4 Using sort_union(a,b); Using where +select * from t1 where a=4 or b=4; +a filler b +4 zz 4 +5 qq 4 +4 filler 4 +4 qq 5 +4 4 0 +4 filler 4 +4 5 0 +select * from t1 ignore index(a,b) where a=4 or b=4; +a filler b +4 filler 4 +4 filler 4 +4 5 0 +4 4 0 +4 qq 5 +5 qq 4 +4 zz 4 +must use union, not sort-union: +explain select * from t2 where a=4 or b=4; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 index_merge a,b a,b 5,5 NULL 7 Using union(a,b); Using where +select * from t2 where a=4 or b=4; +a filler b +4 5 0 +4 zz 4 +5 qq 4 +4 filler 4 +4 qq 5 +4 4 0 +4 filler 4 +drop table t1, t2; diff --git a/mysql-test/t/index_merge.test b/mysql-test/t/index_merge.test index 30eb0b40fca..7d9a4340b0f 100644 --- a/mysql-test/t/index_merge.test +++ b/mysql-test/t/index_merge.test @@ -415,3 +415,46 @@ INSERT INTO t2(a,b) VALUES(1,2); SELECT t2.a FROM t1,t2 WHERE t2.b=2 AND t2.a=1; UNLOCK TABLES; DROP TABLE t1, t2; + +# +# BUG#29740: HA_KEY_SCAN_NOT_ROR wasn't set for HEAP engine +# +CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL, + `filler` char(200) DEFAULT NULL, + `b` int(11) DEFAULT NULL, + KEY `a` (`a`), + KEY `b` (`b`) +) ENGINE=MEMORY DEFAULT CHARSET=latin1; + +insert into t1 values +(0, 'filler', 0), (1, 'filler', 1), (2, 'filler', 2), (3, 'filler', 3), +(4, 'filler', 4), (5, 'filler', 5), (6, 'filler', 6), (7, 'filler', 7), +(8, 'filler', 8), (9, 'filler', 9), (0, 'filler', 0), (1, 'filler', 1), +(2, 'filler', 2), (3, 'filler', 3), (4, 'filler', 4), (5, 'filler', 5), +(6, 'filler', 6), (7, 'filler', 7), (8, 'filler', 8), (9, 'filler', 9), +(10, 'filler', 10), (11, 'filler', 11), (12, 'filler', 12), (13, 'filler', 13), +(14, 'filler', 14), (15, 'filler', 15), (16, 'filler', 16), (17, 'filler', 17), +(18, 'filler', 18), (19, 'filler', 19), (4, '5 ', 0), (5, '4 ', 0), +(4, '4 ', 0), (4, 'qq ', 5), (5, 'qq ', 4), (4, 'zz ', 4); + +create table t2( + `a` int(11) DEFAULT NULL, + `filler` char(200) DEFAULT NULL, + `b` int(11) DEFAULT NULL, + KEY USING BTREE (`a`), + KEY USING BTREE (`b`) +) ENGINE=MEMORY DEFAULT CHARSET=latin1; +insert into t2 select * from t1; + +--echo must use sort-union rather than union: +explain select * from t1 where a=4 or b=4; +select * from t1 where a=4 or b=4; +select * from t1 ignore index(a,b) where a=4 or b=4; + +--echo must use union, not sort-union: +explain select * from t2 where a=4 or b=4; +select * from t2 where a=4 or b=4; + +drop table t1, t2; + diff --git a/sql/ha_heap.h b/sql/ha_heap.h index 18389c1298d..27846ca4a8e 100644 --- a/sql/ha_heap.h +++ b/sql/ha_heap.h @@ -54,8 +54,8 @@ public: ulong index_flags(uint inx, uint part, bool all_parts) const { return ((table->key_info[inx].algorithm == HA_KEY_ALG_BTREE) ? - HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER | HA_READ_RANGE : - HA_ONLY_WHOLE_INDEX); + HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER | HA_READ_RANGE : + HA_ONLY_WHOLE_INDEX | HA_KEY_SCAN_NOT_ROR); } const key_map *keys_to_use_for_scanning() { return &btree_keys; } uint max_supported_keys() const { return MAX_KEY; } @@ -101,9 +101,7 @@ public: enum thr_lock_type lock_type); int cmp_ref(const byte *ref1, const byte *ref2) { - HEAP_PTR ptr1=*(HEAP_PTR*)ref1; - HEAP_PTR ptr2=*(HEAP_PTR*)ref2; - return ptr1 < ptr2? -1 : (ptr1 > ptr2? 1 : 0); + return memcmp(ref1, ref2, sizeof(HEAP_PTR)); } private: void update_key_stats(); diff --git a/sql/opt_range.cc b/sql/opt_range.cc index c3aa1f52556..952e5abfd13 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -6007,27 +6007,24 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree, ROR (Rowid Ordered Retrieval) key scan is a key scan that produces ordered sequence of rowids (ha_xxx::cmp_ref is the comparison function) - An index scan is a ROR scan if it is done using a condition in form + This function is needed to handle a practically-important special case: + an index scan is a ROR scan if it is done using a condition in form - "key1_1=c_1 AND ... AND key1_n=c_n" (1) + "key1_1=c_1 AND ... AND key1_n=c_n" where the index is defined on (key1_1, ..., key1_N [,a_1, ..., a_n]) - and the table has a clustered Primary Key + and the table has a clustered Primary Key defined as - PRIMARY KEY(a_1, ..., a_n, b1, ..., b_k) with first key parts being - identical to uncovered parts ot the key being scanned (2) - - Scans on HASH indexes are not ROR scans, - any range scan on clustered primary key is ROR scan (3) - - Check (1) is made in check_quick_keys() - Check (3) is made check_quick_select() - Check (2) is made by this function. + PRIMARY KEY(a_1, ..., a_n, b1, ..., b_k) + + i.e. the first key parts of it are identical to uncovered parts ot the + key being scanned. This function assumes that the index flags do not + include HA_KEY_SCAN_NOT_ROR flag (that is checked elsewhere). RETURN - TRUE If the scan is ROR-scan - FALSE otherwise + TRUE The scan is ROR-scan + FALSE Otherwise */ static bool is_key_scan_ror(PARAM *param, uint keynr, uint8 nparts) -- cgit v1.2.1 From ecfa8da35c85b60c66b6a603928ebd96acfae93d Mon Sep 17 00:00:00 2001 From: "sergefp@mysql.com" <> Date: Sat, 14 Jul 2007 22:02:10 +0400 Subject: BUG#29740: Make the test result deterministic --- mysql-test/r/index_merge.result | 28 ++++++++++++++-------------- mysql-test/t/index_merge.test | 5 +++++ 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/mysql-test/r/index_merge.result b/mysql-test/r/index_merge.result index c7e4ead9eeb..15aa636d740 100644 --- a/mysql-test/r/index_merge.result +++ b/mysql-test/r/index_merge.result @@ -483,36 +483,36 @@ insert into t2 select * from t1; must use sort-union rather than union: explain select * from t1 where a=4 or b=4; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge a,b a,b 5,5 NULL 4 Using sort_union(a,b); Using where +1 SIMPLE t1 index_merge a,b a,b 5,5 NULL # Using sort_union(a,b); Using where select * from t1 where a=4 or b=4; a filler b -4 zz 4 -5 qq 4 -4 filler 4 -4 qq 5 4 4 0 -4 filler 4 4 5 0 +4 filler 4 +4 filler 4 +4 qq 5 +4 zz 4 +5 qq 4 select * from t1 ignore index(a,b) where a=4 or b=4; a filler b +4 4 0 +4 5 0 4 filler 4 4 filler 4 -4 5 0 -4 4 0 4 qq 5 -5 qq 4 4 zz 4 +5 qq 4 must use union, not sort-union: explain select * from t2 where a=4 or b=4; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 index_merge a,b a,b 5,5 NULL 7 Using union(a,b); Using where +1 SIMPLE t2 index_merge a,b a,b 5,5 NULL # Using union(a,b); Using where select * from t2 where a=4 or b=4; a filler b +4 4 0 4 5 0 -4 zz 4 -5 qq 4 4 filler 4 -4 qq 5 -4 4 0 4 filler 4 +4 qq 5 +4 zz 4 +5 qq 4 drop table t1, t2; diff --git a/mysql-test/t/index_merge.test b/mysql-test/t/index_merge.test index 7d9a4340b0f..8c19ab4d7d6 100644 --- a/mysql-test/t/index_merge.test +++ b/mysql-test/t/index_merge.test @@ -448,12 +448,17 @@ create table t2( insert into t2 select * from t1; --echo must use sort-union rather than union: +--replace_column 9 # explain select * from t1 where a=4 or b=4; +--sorted_result select * from t1 where a=4 or b=4; +--sorted_result select * from t1 ignore index(a,b) where a=4 or b=4; --echo must use union, not sort-union: +--replace_column 9 # explain select * from t2 where a=4 or b=4; +--sorted_result select * from t2 where a=4 or b=4; drop table t1, t2; -- cgit v1.2.1 From e717f9d2eb1f6f60975fefd5136281cb87ca1049 Mon Sep 17 00:00:00 2001 From: "evgen@moonbone.local" <> Date: Sat, 14 Jul 2007 22:43:58 +0400 Subject: Bug#29729: Wrong conversion error led to an empty result set. The Field_newdate::store when storing a DATETIME value was returning the 'value was cut' error even if the thd->count_cuted_fields flag is set to CHECK_FIELD_IGNORE. This made range optimizr think that there is no appropriate data in the table and thus to return an empty set. Now the Field_newdate::store function returns conversion error only if the thd->count_cuted_fields flag isn't set to CHECK_FIELD_IGNORE. --- mysql-test/r/type_time.result | 13 +++++++++++++ mysql-test/t/type_time.test | 15 +++++++++++++++ sql/field.cc | 3 ++- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/type_time.result b/mysql-test/r/type_time.result index 71bd8b68a0b..def94bd707b 100644 --- a/mysql-test/r/type_time.result +++ b/mysql-test/r/type_time.result @@ -109,3 +109,16 @@ select 1 from t1 where cast('100:00:00' as time) between f1 and f2; 1 1 drop table t1; +CREATE TABLE t1 ( +f2 date NOT NULL, +f3 int(11) unsigned NOT NULL default '0', +PRIMARY KEY (f3, f2) +); +insert into t1 values('2007-07-01', 1); +insert into t1 values('2007-07-01', 2); +insert into t1 values('2007-07-02', 1); +insert into t1 values('2007-07-02', 2); +SELECT sum(f3) FROM t1 where f2='2007-07-01 00:00:00' group by f2; +sum(f3) +3 +drop table t1; diff --git a/mysql-test/t/type_time.test b/mysql-test/t/type_time.test index 82d701e29b5..bc4f850dfee 100644 --- a/mysql-test/t/type_time.test +++ b/mysql-test/t/type_time.test @@ -58,3 +58,18 @@ create table t1(f1 time, f2 time); insert into t1 values('20:00:00','150:00:00'); select 1 from t1 where cast('100:00:00' as time) between f1 and f2; drop table t1; + +# +# Bug#29729: Wrong conversion error led to an empty result set. +# +CREATE TABLE t1 ( + f2 date NOT NULL, + f3 int(11) unsigned NOT NULL default '0', + PRIMARY KEY (f3, f2) +); +insert into t1 values('2007-07-01', 1); +insert into t1 values('2007-07-01', 2); +insert into t1 values('2007-07-02', 1); +insert into t1 values('2007-07-02', 2); +SELECT sum(f3) FROM t1 where f2='2007-07-01 00:00:00' group by f2; +drop table t1; diff --git a/sql/field.cc b/sql/field.cc index 2e227f0e67e..993c1fb3c4f 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5271,7 +5271,8 @@ int Field_newdate::store(const char *from,uint len,CHARSET_INFO *cs) else { tmp= l_time.day + l_time.month*32 + l_time.year*16*32; - if (!error && (ret != MYSQL_TIMESTAMP_DATE)) + if (!error && (ret != MYSQL_TIMESTAMP_DATE) && + thd->count_cuted_fields != CHECK_FIELD_IGNORE) error= 3; // Datetime was cut (note) } -- cgit v1.2.1 From 975d22327ef5235222307f2c015649d3558b5ea7 Mon Sep 17 00:00:00 2001 From: "evgen@moonbone.local" <> Date: Sun, 15 Jul 2007 21:51:36 +0400 Subject: Extended fix for the bug#29555. The get_time_value function is added. It is used to obtain TIME values both from items the can return time as an integer and from items that can return time only as a string. The Arg_comparator::compare_datetime function now uses pointer to a getter function to obtain values to compare. Now this function is also used for comparison of TIME values. The get_value_func variable is added to the Arg_comparator class. It points to a getter function for the DATE/DATETIME/TIME comparator. --- mysql-test/r/type_time.result | 6 ++++ mysql-test/t/type_time.test | 4 +++ sql/item_cmpfunc.cc | 81 +++++++++++++++++++++++++++++++++++++++---- sql/item_cmpfunc.h | 2 ++ 4 files changed, 86 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/type_time.result b/mysql-test/r/type_time.result index def94bd707b..96bf23109df 100644 --- a/mysql-test/r/type_time.result +++ b/mysql-test/r/type_time.result @@ -103,6 +103,12 @@ cast('100:55:50' as time) > cast('024:00:00' as time) select cast('300:55:50' as time) > cast('240:00:00' as time); cast('300:55:50' as time) > cast('240:00:00' as time) 1 +create table t1 (f1 time); +insert into t1 values ('24:00:00'); +select cast('24:00:00' as time) = (select f1 from t1); +cast('24:00:00' as time) = (select f1 from t1) +1 +drop table t1; create table t1(f1 time, f2 time); insert into t1 values('20:00:00','150:00:00'); select 1 from t1 where cast('100:00:00' as time) between f1 and f2; diff --git a/mysql-test/t/type_time.test b/mysql-test/t/type_time.test index bc4f850dfee..5fc763be7fe 100644 --- a/mysql-test/t/type_time.test +++ b/mysql-test/t/type_time.test @@ -50,6 +50,10 @@ select cast('300:55:50' as time) < cast('240:00:00' as time); select cast('100:55:50' as time) > cast('24:00:00' as time); select cast('100:55:50' as time) > cast('024:00:00' as time); select cast('300:55:50' as time) > cast('240:00:00' as time); +create table t1 (f1 time); +insert into t1 values ('24:00:00'); +select cast('24:00:00' as time) = (select f1 from t1); +drop table t1; # # Bug#29739: Incorrect time comparison in BETWEEN. diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 555384b2bfc..8e16dfb4145 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -666,6 +666,68 @@ Arg_comparator::can_compare_as_dates(Item *a, Item *b, ulonglong *const_value) } +/* + Retrieves correct TIME value from the given item. + + SYNOPSIS + get_time_value() + thd thread handle + item_arg [in/out] item to retrieve TIME value from + cache_arg [in/out] pointer to place to store the caching item to + warn_item [in] unused + is_null [out] TRUE <=> the item_arg is null + + DESCRIPTION + Retrieves the correct TIME value from given item for comparison by the + compare_datetime() function. + If item's result can be compared as longlong then its int value is used + and a value returned by get_time function is used otherwise. + If an item is a constant one then its value is cached and it isn't + get parsed again. An Item_cache_int object is used for caching values. It + seamlessly substitutes the original item. The cache item is marked as + non-constant to prevent re-caching it again. + + RETURN + obtained value +*/ + +ulonglong +get_time_value(THD *thd, Item ***item_arg, Item **cache_arg, + Item *warn_item, bool *is_null) +{ + ulonglong value; + Item *item= **item_arg; + MYSQL_TIME ltime; + + if (item->result_as_longlong()) + { + value= item->val_int(); + *is_null= item->null_value; + } + else + { + *is_null= item->get_time(<ime); + if (!is_null) + value= TIME_to_ulonglong_datetime(<ime); + } + /* + Do not cache GET_USER_VAR() function as its const_item() may return TRUE + for the current thread but it still may change during the execution. + */ + if (item->const_item() && cache_arg && (item->type() != Item::FUNC_ITEM || + ((Item_func*)item)->functype() != Item_func::GUSERVAR_FUNC)) + { + Item_cache_int *cache= new Item_cache_int(); + /* Mark the cache as non-const to prevent re-caching. */ + cache->set_used_tables(1); + cache->store(item, value); + *cache_arg= cache; + *item_arg= cache_arg; + } + return value; +} + + int Arg_comparator::set_cmp_func(Item_bool_func2 *owner_arg, Item **a1, Item **a2, Item_result type) @@ -704,6 +766,7 @@ int Arg_comparator::set_cmp_func(Item_bool_func2 *owner_arg, } is_nulls_eq= test(owner && owner->functype() == Item_func::EQUAL_FUNC); func= &Arg_comparator::compare_datetime; + get_value_func= &get_datetime_value; return 0; } else if (type == STRING_RESULT && (*a)->field_type() == MYSQL_TYPE_TIME && @@ -712,9 +775,11 @@ int Arg_comparator::set_cmp_func(Item_bool_func2 *owner_arg, /* Compare TIME values as integers. */ thd= current_thd; owner= owner_arg; - func= ((test(owner && owner->functype() == Item_func::EQUAL_FUNC)) ? - &Arg_comparator::compare_e_int : - &Arg_comparator::compare_int_unsigned); + a_cache= 0; + b_cache= 0; + is_nulls_eq= test(owner && owner->functype() == Item_func::EQUAL_FUNC); + func= &Arg_comparator::compare_datetime; + get_value_func= &get_time_value; return 0; } @@ -735,8 +800,10 @@ void Arg_comparator::set_datetime_cmp_func(Item **a1, Item **b1) b_cache= 0; is_nulls_eq= FALSE; func= &Arg_comparator::compare_datetime; + get_value_func= &get_datetime_value; } + /* Retrieves correct DATETIME value from given item. @@ -850,8 +917,8 @@ int Arg_comparator::compare_datetime() bool is_null= FALSE; ulonglong a_value, b_value; - /* Get DATE/DATETIME value of the 'a' item. */ - a_value= get_datetime_value(thd, &a, &a_cache, *b, &is_null); + /* Get DATE/DATETIME/TIME value of the 'a' item. */ + a_value= (*get_value_func)(thd, &a, &a_cache, *b, &is_null); if (!is_nulls_eq && is_null) { if (owner) @@ -859,8 +926,8 @@ int Arg_comparator::compare_datetime() return -1; } - /* Get DATE/DATETIME value of the 'b' item. */ - b_value= get_datetime_value(thd, &b, &b_cache, *a, &is_null); + /* Get DATE/DATETIME/TIME value of the 'b' item. */ + b_value= (*get_value_func)(thd, &b, &b_cache, *a, &is_null); if (is_null) { if (owner) diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 79091b9c87d..9afc0507817 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -42,6 +42,8 @@ class Arg_comparator: public Sql_alloc bool is_nulls_eq; // TRUE <=> compare for the EQUAL_FUNC enum enum_date_cmp_type { CMP_DATE_DFLT= 0, CMP_DATE_WITH_DATE, CMP_DATE_WITH_STR, CMP_STR_WITH_DATE }; + ulonglong (*get_value_func)(THD *thd, Item ***item_arg, Item **cache_arg, + Item *warn_item, bool *is_null); public: DTCollation cmp_collation; -- cgit v1.2.1 From 9dc929f2b40e5270e2eb93ba694d39b35e252eb6 Mon Sep 17 00:00:00 2001 From: "evgen@moonbone.local" <> Date: Sun, 15 Jul 2007 23:40:57 +0400 Subject: item_cmpfunc.cc: A comment changed. --- sql/item_cmpfunc.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 8e16dfb4145..161a3f7bb19 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -673,7 +673,7 @@ Arg_comparator::can_compare_as_dates(Item *a, Item *b, ulonglong *const_value) get_time_value() thd thread handle item_arg [in/out] item to retrieve TIME value from - cache_arg [in/out] pointer to place to store the caching item to + cache_arg [in/out] pointer to place to store the cache item to warn_item [in] unused is_null [out] TRUE <=> the item_arg is null @@ -683,8 +683,8 @@ Arg_comparator::can_compare_as_dates(Item *a, Item *b, ulonglong *const_value) If item's result can be compared as longlong then its int value is used and a value returned by get_time function is used otherwise. If an item is a constant one then its value is cached and it isn't - get parsed again. An Item_cache_int object is used for caching values. It - seamlessly substitutes the original item. The cache item is marked as + get parsed again. An Item_cache_int object is used for for cached values. + It seamlessly substitutes the original item. The cache item is marked as non-constant to prevent re-caching it again. RETURN -- cgit v1.2.1 From 49db78b382b3c27d73cd9be2bcac26fa43678905 Mon Sep 17 00:00:00 2001 From: "evgen@moonbone.local" <> Date: Mon, 16 Jul 2007 00:59:47 +0400 Subject: item_cmpfunc.cc: Fixed compiler warning. --- sql/item_cmpfunc.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 161a3f7bb19..a89f6337f5f 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -707,8 +707,7 @@ get_time_value(THD *thd, Item ***item_arg, Item **cache_arg, else { *is_null= item->get_time(<ime); - if (!is_null) - value= TIME_to_ulonglong_datetime(<ime); + value= !is_null ? TIME_to_ulonglong_datetime(<ime) : 0; } /* Do not cache GET_USER_VAR() function as its const_item() may return TRUE -- cgit v1.2.1 From 17654758a4198761b0a91bef4e93441724b951aa Mon Sep 17 00:00:00 2001 From: "evgen@moonbone.local" <> Date: Mon, 16 Jul 2007 01:03:58 +0400 Subject: item_cmpfunc.cc: A typo fixed. --- sql/item_cmpfunc.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index a89f6337f5f..86eb10d50b0 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -707,7 +707,7 @@ get_time_value(THD *thd, Item ***item_arg, Item **cache_arg, else { *is_null= item->get_time(<ime); - value= !is_null ? TIME_to_ulonglong_datetime(<ime) : 0; + value= !*is_null ? TIME_to_ulonglong_datetime(<ime) : 0; } /* Do not cache GET_USER_VAR() function as its const_item() may return TRUE -- cgit v1.2.1 From 651e6ffa6657eb328e50cca2e3ac714234166c7e Mon Sep 17 00:00:00 2001 From: "sergefp@mysql.com" <> Date: Tue, 17 Jul 2007 19:51:50 +0400 Subject: [pb problem]: ha_heap->clone() fails on windows because of mess with '/' and '\' in path delimiters: - Fix this by creating new handler with exactly the same path line as was passed to ha_create/ha_open. --- sql/ha_heap.cc | 20 ++++++++++++++++++++ sql/ha_heap.h | 1 + sql/opt_range.cc | 8 ++++++++ 3 files changed, 29 insertions(+) diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc index 8838aa99c1a..62e6d0c47ee 100644 --- a/sql/ha_heap.cc +++ b/sql/ha_heap.cc @@ -114,6 +114,26 @@ int ha_heap::close(void) } +/* + Create a copy of this table + + DESCRIPTION + Do same as default implementation but use file->s->name instead of + table->s->path. This is needed by Windows where the clone() call sees + '/'-delimited path in table->s->path, while ha_peap::open() was called + with '\'-delimited path. +*/ + +handler *ha_heap::clone(MEM_ROOT *mem_root) +{ + handler *new_handler= get_new_handler(table, mem_root, table->s->db_type); + if (new_handler && !new_handler->ha_open(file->s->name, table->db_stat, + HA_OPEN_IGNORE_IF_LOCKED)) + return new_handler; + return NULL; +} + + /* Compute which keys to use for scanning diff --git a/sql/ha_heap.h b/sql/ha_heap.h index 27846ca4a8e..23583d0a6a7 100644 --- a/sql/ha_heap.h +++ b/sql/ha_heap.h @@ -32,6 +32,7 @@ class ha_heap: public handler public: ha_heap(TABLE *table); ~ha_heap() {} + handler *clone(MEM_ROOT *mem_root); const char *table_type() const { return (table->in_use->variables.sql_mode & MODE_MYSQL323) ? diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 952e5abfd13..76e78c7e9b8 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1131,6 +1131,14 @@ int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler) THD *thd= current_thd; if (!(file= head->file->clone(thd->mem_root))) { + /* + Manually set the error flag. Note: there seems to be quite a few + places where a failure could cause the server to "hang" the client by + sending no response to a query. ATM those are not real errors because + the storage engine calls in question happen to never fail with the + existing storage engines. + */ + thd->net.report_error= 1; /* Caller will free the memory */ goto failure; } -- cgit v1.2.1 From b38206978dd29149bf414a46b25571633ed778bc Mon Sep 17 00:00:00 2001 From: "sergefp@mysql.com" <> Date: Tue, 17 Jul 2007 22:46:51 +0400 Subject: Small comments fix --- sql/opt_range.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 76e78c7e9b8..65acecc0b87 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -5824,6 +5824,11 @@ check_quick_select(PARAM *param,uint idx,SEL_ARG *tree) param->is_ror_scan is cleared if the function detects that the key scan is not a Rowid-Ordered Retrieval scan ( see comments for is_key_scan_ror function for description of which key scans are ROR scans) + + RETURN + #records E(#records) for given subtree + HA_POS_ERROR if subtree cannot be used for record retrieval + */ static ha_rows -- cgit v1.2.1 From 2e21c6e7715e61c548428ba243a800e0b97cf034 Mon Sep 17 00:00:00 2001 From: "sergefp@mysql.com" <> Date: Wed, 18 Jul 2007 00:29:25 +0400 Subject: Mark deadcode for gcov --- sql/ha_heap.cc | 2 +- sql/opt_range.cc | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc index 62e6d0c47ee..9ebc5aecde2 100644 --- a/sql/ha_heap.cc +++ b/sql/ha_heap.cc @@ -129,7 +129,7 @@ handler *ha_heap::clone(MEM_ROOT *mem_root) handler *new_handler= get_new_handler(table, mem_root, table->s->db_type); if (new_handler && !new_handler->ha_open(file->s->name, table->db_stat, HA_OPEN_IGNORE_IF_LOCKED)) - return new_handler; + return new_handler; /* purecov: inspected */ return NULL; } diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 65acecc0b87..247f0eada49 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1138,9 +1138,9 @@ int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler) the storage engine calls in question happen to never fail with the existing storage engines. */ - thd->net.report_error= 1; + thd->net.report_error= 1; /* purecov: inspected */ /* Caller will free the memory */ - goto failure; + goto failure; /* purecov: inspected */ } if (file->external_lock(thd, F_RDLCK)) goto failure; -- cgit v1.2.1 From 4f579b8d0e3e8bc3d8eb57eca7d3c656c77cb10b Mon Sep 17 00:00:00 2001 From: "sergefp@mysql.com" <> Date: Wed, 18 Jul 2007 11:12:15 +0400 Subject: Mark deadcode for gcov --- sql/ha_heap.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc index 9ebc5aecde2..bf807407df1 100644 --- a/sql/ha_heap.cc +++ b/sql/ha_heap.cc @@ -129,8 +129,8 @@ handler *ha_heap::clone(MEM_ROOT *mem_root) handler *new_handler= get_new_handler(table, mem_root, table->s->db_type); if (new_handler && !new_handler->ha_open(file->s->name, table->db_stat, HA_OPEN_IGNORE_IF_LOCKED)) - return new_handler; /* purecov: inspected */ - return NULL; + return new_handler; + return NULL; /* purecov: inspected */ } -- cgit v1.2.1