-
Norvald H. Ryeng authored
VARIABLES ARE USED This is a regression introduced by the fix for bug #12408412. Problem: Performance regression when using SELECT ... INTO user variables and a WHERE condition on one or more variables in the INTO list. Since the fix for bug #12408412, Item_func_set_user_var objects for user variables that are in the INTO list are constructed by select_dumpvar::prepare(), which makes the Item_func_get_user_var objects for the same variables marked as non-const during optimization and execution. This leads to queries not taking advantage of optimizations that are possible when a user variable is constant throughout the query execution, even if the update only happens after the query has been executed. E.g., the optimizer may choose to do an index scan instead of an index lookup. Also, since the Item_func_set_user_var objects are created in select_dumpvar::prepare(), which is not called during EXPLAIN, the explained plan and the actual plan may be different, since the constness of Item_get_user_var objects may be different. Fix: Revert the change that marks user variables as non-const when used in the INTO list. This reintroduces bug #12408412. Problem in bug #12408412: A SELECT ... INTO query that stores the value of GROUP_CONCAT(@var) into @var crashes the server. The user variable in the SELECT list is represented by an Item_func_get_user_var. Item_func_get_user_var::const_item() returns true for this item throughout query optimization and execution since there are no Item_func_set_user_var items for the same variable. After query execution, in select_dumpvar::send_data(), an Item_func_set_user_var is created for the user variable in the INTO list. Item_func_set_user_var::fix_fields() calls Item_func_set_user_var::set_entry(), which sets update_query_id to the current query. This variable is used by Item_func_get_user_var::const_item() to determine if the variable is read and written in the same query. Item_func_set_user_var::save_item_result() is then called to store the result of GROUP_CONCAT, but Item_func_group_concat::val_str() calls walk() on its arguments with dump_leaf_key() as processor. In dump_leaf_key(), a decision is made on the constness of the Item_func_get_user_var(), which is now different from what it was during optimization and execution, and the server crashes while trying to dereference a null pointer. Fix: Add a new variable Item_func_set_user_var::delayed_non_constness that controls when update_query_id is set: false: by Item_func_set_user_var::fix_fields(), or true: at the end of Item_func_set_user_var::save_item_result(), when the item has been evaluated. This allows select_dumpvar::send_data() to update the user variable without changing constness of the Item_func_get_user_var for the same variable until after the value has been read.
Norvald H. Ryeng authoredVARIABLES ARE USED This is a regression introduced by the fix for bug #12408412. Problem: Performance regression when using SELECT ... INTO user variables and a WHERE condition on one or more variables in the INTO list. Since the fix for bug #12408412, Item_func_set_user_var objects for user variables that are in the INTO list are constructed by select_dumpvar::prepare(), which makes the Item_func_get_user_var objects for the same variables marked as non-const during optimization and execution. This leads to queries not taking advantage of optimizations that are possible when a user variable is constant throughout the query execution, even if the update only happens after the query has been executed. E.g., the optimizer may choose to do an index scan instead of an index lookup. Also, since the Item_func_set_user_var objects are created in select_dumpvar::prepare(), which is not called during EXPLAIN, the explained plan and the actual plan may be different, since the constness of Item_get_user_var objects may be different. Fix: Revert the change that marks user variables as non-const when used in the INTO list. This reintroduces bug #12408412. Problem in bug #12408412: A SELECT ... INTO query that stores the value of GROUP_CONCAT(@var) into @var crashes the server. The user variable in the SELECT list is represented by an Item_func_get_user_var. Item_func_get_user_var::const_item() returns true for this item throughout query optimization and execution since there are no Item_func_set_user_var items for the same variable. After query execution, in select_dumpvar::send_data(), an Item_func_set_user_var is created for the user variable in the INTO list. Item_func_set_user_var::fix_fields() calls Item_func_set_user_var::set_entry(), which sets update_query_id to the current query. This variable is used by Item_func_get_user_var::const_item() to determine if the variable is read and written in the same query. Item_func_set_user_var::save_item_result() is then called to store the result of GROUP_CONCAT, but Item_func_group_concat::val_str() calls walk() on its arguments with dump_leaf_key() as processor. In dump_leaf_key(), a decision is made on the constness of the Item_func_get_user_var(), which is now different from what it was during optimization and execution, and the server crashes while trying to dereference a null pointer. Fix: Add a new variable Item_func_set_user_var::delayed_non_constness that controls when update_query_id is set: false: by Item_func_set_user_var::fix_fields(), or true: at the end of Item_func_set_user_var::save_item_result(), when the item has been evaluated. This allows select_dumpvar::send_data() to update the user variable without changing constness of the Item_func_get_user_var for the same variable until after the value has been read.
Loading