diff options
author | Georgi Kodinov <kgeorge@mysql.com> | 2008-10-17 13:55:16 +0300 |
---|---|---|
committer | Georgi Kodinov <kgeorge@mysql.com> | 2008-10-17 13:55:16 +0300 |
commit | e7a6e86f78998e35e1912f377006a35db3705246 (patch) | |
tree | 6e18641ac6cca2fb89f3402f3b7e299c9ecbe1a9 /sql | |
parent | 3ad228d7fba6fa2e5b98569f798583b8f8b90db9 (diff) | |
download | mariadb-git-e7a6e86f78998e35e1912f377006a35db3705246.tar.gz |
Bug #38637: COUNT DISTINCT prevents NULL testing in HAVING clause
IS NULL was not checking the correct row in a HAVING context.
At the first row of a new group (where the HAVING clause is evaluated)
the column and SELECT list references in the HAVING clause should
refer to the last row of the previous group and not to the current one.
This was not done for IS NULL, because it was using Item::is_null() doesn't
have a Item_is_null_result() counterpart to access the data from the
last row of the previous group. Note that all the Item::val_xxx() functions
(e.g. Item::val_int()) have their _result counterparts (e.g. Item::val_int_result()).
Fixed by implementing a is_null_result() (similarly to int_result()) and
calling this instead of is_null() column and SELECT list references inside
the HAVING clause.
mysql-test/r/having.result:
Bug #38637: test case
mysql-test/t/having.test:
Bug #38637: test case
sql/item.cc:
Bug #38637: implement Item::is_null_result() and call it
from Item_ref and Item_field as appropriate.
sql/item.h:
Bug #38637: implement Item::is_null_result() and call it
from Item_ref and Item_field as appropriate.
sql/item_func.cc:
Bug #38637: implement Item::is_null_result() and call it
from Item_ref and Item_field as appropriate.
sql/item_func.h:
Bug #38637: implement Item::is_null_result() and call it
from Item_ref and Item_field as appropriate.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item.cc | 19 | ||||
-rw-r--r-- | sql/item.h | 3 | ||||
-rw-r--r-- | sql/item_func.cc | 9 | ||||
-rw-r--r-- | sql/item_func.h | 1 |
4 files changed, 31 insertions, 1 deletions
diff --git a/sql/item.cc b/sql/item.cc index 182f4abdfe6..e71268724b4 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -2041,6 +2041,12 @@ bool Item_field::val_bool_result() } +bool Item_field::is_null_result() +{ + return (null_value=result_field->is_null()); +} + + bool Item_field::eq(const Item *item, bool binary_cmp) const { Item *real_item= ((Item *) item)->real_item(); @@ -5626,6 +5632,15 @@ double Item_ref::val_result() } +bool Item_ref::is_null_result() +{ + if (result_field) + return (null_value=result_field->is_null()); + + return is_null(); +} + + longlong Item_ref::val_int_result() { if (result_field) @@ -5731,7 +5746,9 @@ String *Item_ref::val_str(String* tmp) bool Item_ref::is_null() { DBUG_ASSERT(fixed); - return (*ref)->is_null(); + bool tmp=(*ref)->is_null_result(); + null_value=(*ref)->null_value; + return tmp; } diff --git a/sql/item.h b/sql/item.h index 250bb3f67ef..1058cc5dbb8 100644 --- a/sql/item.h +++ b/sql/item.h @@ -652,6 +652,7 @@ public: virtual my_decimal *val_decimal_result(my_decimal *val) { return val_decimal(val); } virtual bool val_bool_result() { return val_bool(); } + virtual bool is_null_result() { return is_null(); } /* bit map of tables used by item */ virtual table_map used_tables() const { return (table_map) 0L; } @@ -1301,6 +1302,7 @@ public: String *str_result(String* tmp); my_decimal *val_decimal_result(my_decimal *); bool val_bool_result(); + bool is_null_result(); bool send(Protocol *protocol, String *str_arg); void reset_field(Field *f); bool fix_fields(THD *, Item **); @@ -1942,6 +1944,7 @@ public: String *str_result(String* tmp); my_decimal *val_decimal_result(my_decimal *); bool val_bool_result(); + bool is_null_result(); bool send(Protocol *prot, String *tmp); void make_field(Send_field *field); bool fix_fields(THD *, Item **); diff --git a/sql/item_func.cc b/sql/item_func.cc index e663e1fcf83..382fea6dfe2 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -4283,6 +4283,15 @@ my_decimal *Item_func_set_user_var::val_decimal_result(my_decimal *val) } +bool Item_func_set_user_var::is_null_result() +{ + DBUG_ASSERT(fixed == 1); + check(TRUE); + update(); // Store expression + return is_null(); +} + + void Item_func_set_user_var::print(String *str) { str->append(STRING_WITH_LEN("(@")); diff --git a/sql/item_func.h b/sql/item_func.h index 6dcf32cba07..8c7becb681b 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1299,6 +1299,7 @@ public: longlong val_int_result(); String *str_result(String *str); my_decimal *val_decimal_result(my_decimal *); + bool is_null_result(); bool update_hash(void *ptr, uint length, enum Item_result type, CHARSET_INFO *cs, Derivation dv, bool unsigned_arg); bool send(Protocol *protocol, String *str_arg); |