summaryrefslogtreecommitdiff
path: root/sql/item_sum.h
diff options
context:
space:
mode:
authorAlexey Kopytov <Alexey.Kopytov@Sun.com>2010-08-27 13:44:35 +0400
committerAlexey Kopytov <Alexey.Kopytov@Sun.com>2010-08-27 13:44:35 +0400
commitd7d0f6390b8d95b34ffb79f1a77ab11657e064a8 (patch)
tree6fb2439f226113dcbabc50c14f731cd8e71a2994 /sql/item_sum.h
parent27d5b6e57fa9f78773002a3b6ae37cfb23b37547 (diff)
downloadmariadb-git-d7d0f6390b8d95b34ffb79f1a77ab11657e064a8.tar.gz
Bug #54465: assert: field_types == 0 || field_types[field_pos]
== MYSQL_TYPE_LONGLONG A MIN/MAX() function with a subquery as its argument could lead to a debug assertion on debug builds or wrong data on release ones. The problem was a combination of the following factors: - Item_sum_hybrid::fix_fields() might use the argument (args[0]) to calculate 'hybrid_field_type' which was later used to decide how the data should be sent to the client. - Item_sum::make_field() might use the argument again to calculate the field's type when sending result set metadata to the client. - The argument could be changed in between these two calls via Item::set_arg() leading to inconsistent metadata being reported. Here is what was happening for the bug's test case: 1. Item_sum_hybrid::fix_fields() calculates hybrid_field_type as MYSQL_TYPE_LONGLONG based on args[0] which is an Item::SUBSELECT_ITEM at that time. 2. A temporary table is created to execute the query. create_tmp_field_from_item() creates a Field_long object according to the subselect's max_length. 3. The subselect item in Item_sum_hybrid is replaced by the Item_field object referencing the newly created Field_long. 4. Item_sum::make_field() rightfully returns the MYSQL_TYPE_LONG type when calculating the result set metadata. 5. When sending the actual data, Item::send() relies on the virtual field_type() function which in our case returns previously calculated hybrid_field_type == MYSQL_TYPE_LONGLONG. It looks like the only solution is to never refer to the argument's metadata after the result metadata has been calculated in fix_fields(), since the argument itself may be different by then. In this sense, Item_sum::make_field() should never be used, because it may rely on the argument's metadata and is only called after fix_fields(). The "default" implementation in Item::make_field() should be used instead as it relies only on field_type(), but not on the argument's type. Fixed by removing Item_sum::make_field() so that the superclass implementation Item::make_field() is always used. mysql-test/r/func_group.result: Added a test case for bug #54465. mysql-test/t/func_group.test: Added a test case for bug #54465. sql/item_sum.cc: Removed Item_sum::make_field() so that the superclass implementation Item::make_field() is always used. sql/item_sum.h: Removed Item_sum::make_field() so that the superclass implementation Item::make_field() is always used.
Diffstat (limited to 'sql/item_sum.h')
-rw-r--r--sql/item_sum.h1
1 files changed, 0 insertions, 1 deletions
diff --git a/sql/item_sum.h b/sql/item_sum.h
index fe05858ab1d..26290a812f4 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -339,7 +339,6 @@ public:
forced_const= TRUE;
}
virtual bool const_item() const { return forced_const; }
- void make_field(Send_field *field);
virtual void print(String *str, enum_query_type query_type);
void fix_num_length_and_dec();