diff options
author | Gleb Shchepa <gshchepa@mysql.com> | 2008-10-08 02:34:00 +0500 |
---|---|---|
committer | Gleb Shchepa <gshchepa@mysql.com> | 2008-10-08 02:34:00 +0500 |
commit | f48b42e77657dd2e27380201631fd0f137863b85 (patch) | |
tree | 384f8d90fd9749658c189cb58badeb9a8114b295 /sql/table.cc | |
parent | 1ce81aac15f0e7a89aef78f8e25ec7976f37972c (diff) | |
download | mariadb-git-f48b42e77657dd2e27380201631fd0f137863b85.tar.gz |
Bug #38691: segfault/abort in ``UPDATE ...JOIN'' while
``FLUSH TABLES WITH READ LOCK''
Concurrent execution of 1) multitable update with a
NATURAL/USING join and 2) a such query as "FLUSH TABLES
WITH READ LOCK" or "ALTER TABLE" of updating table led
to a server crash.
The mysql_multi_update_prepare() function call is optimized
to lock updating tables only, so it postpones locking to
the last, and if locking fails, it does cleanup of modified
syntax structures and repeats a query analysis. However,
that cleanup procedure was incomplete for NATURAL/USING join
syntax data: 1) some Field_item items pointed into freed
table structures, and 2) the TABLE_LIST::join_columns fields
was not reset.
Major change:
short-living Field *Natural_join_column::table_field has
been replaced with long-living Item*.
mysql-test/r/lock_multi.result:
Added test case for bug #38691.
mysql-test/t/lock_multi.test:
Added test case for bug #38691.
sql/item.cc:
Bug #38691: segfault/abort in ``UPDATE ...JOIN'' while
``FLUSH TABLES WITH READ LOCK''
The Item_field constructor has been modified to allocate
and copy original database/table/field names always (not
during PS preparation/1st execution only), because
an initialization of Item_field items with a pointer to
short-living Field structures is a common practice.
sql/sql_base.cc:
Bug #38691: segfault/abort in ``UPDATE ...JOIN'' while
``FLUSH TABLES WITH READ LOCK''
1) Type adjustment for Natural_join_column::table_field
(Field to Item_field);
2) The setup_natural_join_row_types function has been
updated to take into account new
first_natural_join_processing flag to skip unnecessary
reinitialization of Natural_join_column::join_columns
during table reopening after lock_tables() failure
(like the 'first_execution' flag for PS).
sql/sql_lex.cc:
Bug #38691: segfault/abort in ``UPDATE ...JOIN'' while
``FLUSH TABLES WITH READ LOCK''
Initialization of the new
st_select_lex::first_natural_join_processing flag has
been added.
sql/sql_lex.h:
Bug #38691: segfault/abort in ``UPDATE ...JOIN'' while
``FLUSH TABLES WITH READ LOCK''
The st_select_lex::first_natural_join_processing flag
has been added to skip unnecessary rebuilding of
NATURAL/USING JOIN structures during table reopening
after lock_tables failure.
sql/sql_update.cc:
Bug #38691: segfault/abort in ``UPDATE ...JOIN'' while
``FLUSH TABLES WITH READ LOCK''
Extra cleanup calls have been added to reset
Natural_join_column::table_field items.
sql/table.cc:
Bug #38691: segfault/abort in ``UPDATE ...JOIN'' while
``FLUSH TABLES WITH READ LOCK''
Type adjustment for Natural_join_column::table_field
(Field to Item_field).
sql/table.h:
Bug #38691: segfault/abort in ``UPDATE ...JOIN'' while
``FLUSH TABLES WITH READ LOCK''
Type of the Natural_join_column::table_field field has
been changed from Field that points into short-living
TABLE memory to long-living Item_field that can be
linked to (fixed) reopened table.
Diffstat (limited to 'sql/table.cc')
-rw-r--r-- | sql/table.cc | 24 |
1 files changed, 14 insertions, 10 deletions
diff --git a/sql/table.cc b/sql/table.cc index 7fe9aa774f3..3abd2c24c94 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2191,7 +2191,7 @@ TABLE_LIST *TABLE_LIST::find_underlying_table(TABLE *table_to_find) } /* - cleunup items belonged to view fields translation table + cleanup items belonged to view fields translation table SYNOPSIS TABLE_LIST::cleanup_items() @@ -2637,10 +2637,10 @@ Natural_join_column::Natural_join_column(Field_translator *field_param, } -Natural_join_column::Natural_join_column(Field *field_param, +Natural_join_column::Natural_join_column(Item_field *field_param, TABLE_LIST *tab) { - DBUG_ASSERT(tab->table == field_param->table); + DBUG_ASSERT(tab->table == field_param->field->table); table_field= field_param; view_field= NULL; table_ref= tab; @@ -2668,7 +2668,7 @@ Item *Natural_join_column::create_item(THD *thd) return create_view_field(thd, table_ref, &view_field->item, view_field->name); } - return new Item_field(thd, &thd->lex->current_select->context, table_field); + return table_field; } @@ -2679,7 +2679,7 @@ Field *Natural_join_column::field() DBUG_ASSERT(table_field == NULL); return NULL; } - return table_field; + return table_field->field; } @@ -2811,7 +2811,7 @@ void Field_iterator_natural_join::next() cur_column_ref= column_ref_it++; DBUG_ASSERT(!cur_column_ref || ! cur_column_ref->table_field || cur_column_ref->table_ref->table == - cur_column_ref->table_field->table); + cur_column_ref->table_field->field->table); } @@ -2975,7 +2975,7 @@ GRANT_INFO *Field_iterator_table_ref::grant() */ Natural_join_column * -Field_iterator_table_ref::get_or_create_column_ref(TABLE_LIST *parent_table_ref) +Field_iterator_table_ref::get_or_create_column_ref(THD *thd, TABLE_LIST *parent_table_ref) { Natural_join_column *nj_col; bool is_created= TRUE; @@ -2988,7 +2988,11 @@ Field_iterator_table_ref::get_or_create_column_ref(TABLE_LIST *parent_table_ref) { /* The field belongs to a stored table. */ Field *tmp_field= table_field_it.field(); - nj_col= new Natural_join_column(tmp_field, table_ref); + Item_field *tmp_item= + new Item_field(thd, &thd->lex->current_select->context, tmp_field); + if (!tmp_item) + return NULL; + nj_col= new Natural_join_column(tmp_item, table_ref); field_count= table_ref->table->s->fields; } else if (field_it == &view_field_it) @@ -3012,7 +3016,7 @@ Field_iterator_table_ref::get_or_create_column_ref(TABLE_LIST *parent_table_ref) DBUG_ASSERT(nj_col); } DBUG_ASSERT(!nj_col->table_field || - nj_col->table_ref->table == nj_col->table_field->table); + nj_col->table_ref->table == nj_col->table_field->field->table); /* If the natural join column was just created add it to the list of @@ -3077,7 +3081,7 @@ Field_iterator_table_ref::get_natural_column_ref() nj_col= natural_join_it.column_ref(); DBUG_ASSERT(nj_col && (!nj_col->table_field || - nj_col->table_ref->table == nj_col->table_field->table)); + nj_col->table_ref->table == nj_col->table_field->field->table)); return nj_col; } |