diff options
author | Sergey Glukhov <sergey.glukhov@oracle.com> | 2010-10-29 12:23:06 +0400 |
---|---|---|
committer | Sergey Glukhov <sergey.glukhov@oracle.com> | 2010-10-29 12:23:06 +0400 |
commit | 4a23ac20d99118b2127d0e6adae0d8a95655e32e (patch) | |
tree | fd6483a360037b3e154130c107020dde86508925 /sql/sql_select.cc | |
parent | c04bf683fe2582753e8d575e508902245efdd47c (diff) | |
download | mariadb-git-4a23ac20d99118b2127d0e6adae0d8a95655e32e.tar.gz |
Bug#57688 Assertion `!table || (!table->write_set || bitmap_is_set(table->write_set, field
Lines below which were added in the patch for Bug#56814 cause this crash:
+ if (table->table)
+ table->table->maybe_null= FALSE;
Consider following test case:
--
CREATE TABLE t1(f1 INT NOT NULL);
INSERT INTO t1 VALUES (16777214),(0);
SELECT COUNT(*) FROM t1 LEFT JOIN t1 t2
ON 1 WHERE t2.f1 > 1 GROUP BY t2.f1;
DROP TABLE t1;
--
We set TABLE::maybe_null to FALSE for t2 table
and in create_tmp_field() we create appropriate tmp table field
using create_tmp_field_from_item() function instead of
create_tmp_field_from_field. As a result we have
LONGLONG field. As we have GROUP BY clause we calculate
group buffer length, see calc_group_buffer().
Item from group list which is used for calculation
refer to the field from real tables and have LONG type.
So group buffer length become insufficient for storing of
LONGLONG value. It leads to overwriting of wrong memory
area in do_field_int() function which is called from
end_update().
After some investigation I found out that
create_tmp_field_from_item() is used only for OLAP
grouping and can not be used for common grouping
as it could be an incompatibility between tmp
table fields and group buffer length.
We can not remove create_tmp_field_from_item() call from
create_tmp_field as OLAP needs it and we can not use this
function for common grouping. So we should remove setting
TABLE::maybe_null to FALSE from simplify_joins().
In this case we'll get wrong behaviour of
list_contains_unique_index() back. To fix it we
could use Field::real_maybe_null() check instead of
Field::maybe_null() and add addition check of
TABLE_LIST::outer_join.
mysql-test/r/group_by.result:
test case
mysql-test/r/join_outer.result:
test case
mysql-test/t/group_by.test:
test case
mysql-test/t/join_outer.test:
test case
sql/sql_select.cc:
--remove wrong code
--use Field::real_maybe_null() check instead of
Field::maybe_null() and add addition check of
TABLE_LIST::outer_join
Diffstat (limited to 'sql/sql_select.cc')
-rw-r--r-- | sql/sql_select.cc | 11 |
1 files changed, 3 insertions, 8 deletions
diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 11acd0685a8..9767839b5bf 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8832,13 +8832,6 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top) that reject nulls => the outer join can be replaced by an inner join. */ table->outer_join= 0; - /* - Update TABLE::maybe_null field as it could have - the value(maybe_null==TRUE) based on the assumption - that this join is outer(see setup_table_map() func). - */ - if (table->table) - table->table->maybe_null= FALSE; if (table->on_expr) { /* Add on expression to the where condition. */ @@ -13219,6 +13212,8 @@ static bool list_contains_unique_index(TABLE *table, bool (*find_func) (Field *, void *), void *data) { + if (table->pos_in_table_list->outer_join) + return 0; for (uint keynr= 0; keynr < table->s->keys; keynr++) { if (keynr == table->s->primary_key || @@ -13232,7 +13227,7 @@ list_contains_unique_index(TABLE *table, key_part < key_part_end; key_part++) { - if (key_part->field->maybe_null() || + if (key_part->field->real_maybe_null() || !find_func(key_part->field, data)) break; } |