From a7fb5aecfd527c6b9274db02dcec69daf06c97a3 Mon Sep 17 00:00:00 2001 From: Chaithra Gopalareddy Date: Fri, 20 Nov 2015 12:30:15 +0530 Subject: Bug#19941403: FATAL_SIGNAL(SIG 6) IN BUILD_EQUAL_ITEMS_FOR_COND | IN SQL/SQL_OPTIMIZER.CC:1657 Problem: At the end of first execution select_lex->prep_where is pointing to a runtime created object (temporary table field). As a result server exits trying to access a invalid pointer during second execution. Analysis: While optimizing the join conditions for the query, after the permanent transformation, optimizer makes a copy of the new where conditions in select_lex->prep_where. "prep_where" is what is used as the "where condition" for the query at the start of execution. W.r.t the query in question, "where" condition is actually pointing to a field in the temporary table. As a result, for the second execution the pointer is no more valid resulting in server exit. Fix: At the end of the first execution, select_lex->where will have the original item of the where condition. Make prep_where the new place where the original item of select->where has to be rolled back. Fixed in 5.7 with the wl#7082 - Move permanent transformations from JOIN::optimize to JOIN::prepare Patch for 5.5 includes the following backports from 5.6: Bugfix for Bug12603141 - This makes the first execute statement in the testcase pass in 5.5 However it was noted later in in Bug16163596 that the above bugfix needed to be modified. Although Bug16163596 is reproducible only with changes done for Bug12582849, we have decided include the fix. Considering that Bug12582849 is related to Bug12603141, the fix is also included here. However this results in Bug16317817, Bug16317685, Bug16739050. So fix for the above three bugs is also part of this patch. --- sql/sql_select.cc | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'sql/sql_select.cc') diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 96f60d46651..96271f26b0f 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -915,7 +915,22 @@ JOIN::optimize() conds= simplify_joins(this, join_list, conds, TRUE); build_bitmap_for_nested_joins(join_list, 0); - sel->prep_where= conds ? conds->copy_andor_structure(thd) : 0; + /* + After permanent transformations above, prep_where created in + st_select_lex::fix_prepare_information() is out-of-date, we need to + refresh it. + For that We must copy "conds" because it contains AND/OR items in a + non-permanent memroot. And this copy must contain real items only, + because the new AND/OR items will not have their argument pointers + restored by rollback_item_tree_changes(). + @see st_select_lex::fix_prepare_information() for problems with this. + @todo in WL#7082 move transformations above to before + st_select_lex::fix_prepare_information(), and remove this second copy + below. + */ + sel->prep_where= conds ? conds->copy_andor_structure(thd, true) : NULL; + if (conds) + thd->change_item_tree_place(&conds, &select_lex->prep_where); if (arena) thd->restore_active_arena(arena, &backup); @@ -9061,7 +9076,7 @@ simplify_joins(JOIN *join, List *join_list, COND *conds, bool top) DBUG_ASSERT(expr); table->on_expr= expr; - table->prep_on_expr= expr->copy_andor_structure(join->thd); + table->prep_on_expr= expr->copy_andor_structure(join->thd, true); } } nested_join->used_tables= (table_map) 0; -- cgit v1.2.1 From b17a4350696c646e4bc6154a27eeddf363cd39c7 Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Tue, 9 Feb 2016 02:31:47 +0300 Subject: MDEV-6859: scalar subqueries in a comparison produced unexpected result When one evaluates row-based comparison like (X, Y) = (A,B), one should first call bring_value() for the Item that returns row value. If you don't do that and just attempt to read values of X and Y, you get stale values. Semi-join/Materialization can take a row-based comparison apart and make ref access from it. In that case, we need to call bring_value() to get the index lookup components. --- sql/sql_select.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'sql/sql_select.cc') diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f43f506692c..a9b86b5e76b 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -17580,7 +17580,18 @@ int join_read_key2(THD *thd, JOIN_TAB *tab, TABLE *table, TABLE_REF *table_ref) } } + /* + The following is needed when one makes ref (or eq_ref) access from row + comparisons: one must call row->bring_value() to get the new values. + */ + if (tab && tab->bush_children) + { + TABLE_LIST *emb_sj_nest= tab->bush_children->start->emb_sj_nest; + emb_sj_nest->sj_subq_pred->left_expr->bring_value(); + } + /* TODO: Why don't we do "Late NULLs Filtering" here? */ + if (cmp_buffer_with_ref(thd, table, table_ref) || (table->status & (STATUS_GARBAGE | STATUS_NO_PARENT | STATUS_NULL_ROW))) { -- cgit v1.2.1 From 775cccca9f1502ae2f4cf1417d0f94d4872d4630 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Mon, 8 Feb 2016 22:53:40 +0200 Subject: MDEV-7122: Assertion `0' failed in subselect_hash_sj_engine::init The select mentioned in the bug attempted to create a temporary table using the maria storage engine. The table needs to have primary keys such that duplicates can be removed. Unfortunately this use case has a longer than allowed key and the tmp table got created without a temporary key. We must not allow materialization for the subquery if the total key length and key parts is greater than what the storage engine supports. --- sql/sql_select.cc | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'sql/sql_select.cc') diff --git a/sql/sql_select.cc b/sql/sql_select.cc index c960ff37dd9..061e367d725 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -15307,6 +15307,13 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List &fields, if (!table->file) goto err; + /* + Temporary table storage engines must allow keys of at least + HA_MAX_KEY_LENGT and at least HA_MAX_KEY_SEG key parts. + */ + DBUG_ASSERT(table->file->max_key_length() >= HA_MAX_KEY_LENGTH && + table->file->max_key_parts() >= HA_MAX_KEY_SEG); + if (!using_unique_constraint) reclength+= group_null_items; // null flag is stored separately @@ -15940,6 +15947,12 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo, goto err; bzero(seg, sizeof(*seg) * keyinfo->key_parts); + /* + Note that a similar check is performed during + subquery_types_allow_materialization. See MDEV-7122 for more details as + to why. Whenever this changes, it must be updated there as well, for + all tmp_table engines. + */ if (keyinfo->key_length > table->file->max_key_length() || keyinfo->key_parts > table->file->max_key_parts() || share->uniques) @@ -16126,6 +16139,12 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo, goto err; bzero(seg, sizeof(*seg) * keyinfo->key_parts); + /* + Note that a similar check is performed during + subquery_types_allow_materialization. See MDEV-7122 for more details as + to why. Whenever this changes, it must be updated there as well, for + all tmp_table engines. + */ if (keyinfo->key_length > table->file->max_key_length() || keyinfo->key_parts > table->file->max_key_parts() || share->uniques) @@ -16286,6 +16305,12 @@ create_internal_tmp_table_from_heap2(THD *thd, TABLE *table, if (!(new_table.file= get_new_handler(&share, &new_table.mem_root, new_table.s->db_type()))) DBUG_RETURN(1); // End of memory + /* + Temporary table storage engines must allow keys of at least + HA_MAX_KEY_LENGTH and at least HA_MAX_KEY_SEG key parts. + */ + DBUG_ASSERT(new_table.file->max_key_length() >= HA_MAX_KEY_LENGTH && + new_table.file->max_key_parts() >= HA_MAX_KEY_SEG); save_proc_info=thd->proc_info; thd_proc_info(thd, proc_info); -- cgit v1.2.1 From 3c5c04bd2bccbfeb62a86bdc5610b1dcea378dd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Wed, 10 Feb 2016 03:49:11 +0200 Subject: MDEV-7122: Assertion `0' failed in subselect_hash_sj_engine::init Fix test failure when using maria small-block size. We need to query the max_key_length and max_key_parts based on the the tmp table engine. --- sql/sql_select.cc | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'sql/sql_select.cc') diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 061e367d725..b1e22537b37 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -15307,13 +15307,6 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List &fields, if (!table->file) goto err; - /* - Temporary table storage engines must allow keys of at least - HA_MAX_KEY_LENGT and at least HA_MAX_KEY_SEG key parts. - */ - DBUG_ASSERT(table->file->max_key_length() >= HA_MAX_KEY_LENGTH && - table->file->max_key_parts() >= HA_MAX_KEY_SEG); - if (!using_unique_constraint) reclength+= group_null_items; // null flag is stored separately @@ -16305,12 +16298,6 @@ create_internal_tmp_table_from_heap2(THD *thd, TABLE *table, if (!(new_table.file= get_new_handler(&share, &new_table.mem_root, new_table.s->db_type()))) DBUG_RETURN(1); // End of memory - /* - Temporary table storage engines must allow keys of at least - HA_MAX_KEY_LENGTH and at least HA_MAX_KEY_SEG key parts. - */ - DBUG_ASSERT(new_table.file->max_key_length() >= HA_MAX_KEY_LENGTH && - new_table.file->max_key_parts() >= HA_MAX_KEY_SEG); save_proc_info=thd->proc_info; thd_proc_info(thd, proc_info); -- cgit v1.2.1