diff options
author | unknown <sanja@montyprogram.com> | 2012-02-03 13:01:05 +0200 |
---|---|---|
committer | unknown <sanja@montyprogram.com> | 2012-02-03 13:01:05 +0200 |
commit | 79a04a2c9c2cb04bc635b609504e2b9fb57fd23d (patch) | |
tree | 92688c82ffbce89404da4ce64992172932b42092 /sql | |
parent | 046988661d330e48e19af9fd7d9d2ad4f6cbcd1e (diff) | |
download | mariadb-git-79a04a2c9c2cb04bc635b609504e2b9fb57fd23d.tar.gz |
Moving LP BUG#794005 to 5.3 + fixing INSERT of multi-table view.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item.cc | 16 | ||||
-rw-r--r-- | sql/sql_base.cc | 5 | ||||
-rw-r--r-- | sql/sql_delete.cc | 7 | ||||
-rw-r--r-- | sql/sql_derived.cc | 2 | ||||
-rw-r--r-- | sql/sql_insert.cc | 19 | ||||
-rw-r--r-- | sql/sql_load.cc | 2 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 4 | ||||
-rw-r--r-- | sql/sql_update.cc | 4 | ||||
-rw-r--r-- | sql/table.cc | 25 | ||||
-rw-r--r-- | sql/table.h | 3 |
10 files changed, 65 insertions, 22 deletions
diff --git a/sql/item.cc b/sql/item.cc index 8bd5b6fe1a4..f9bbc4aeead 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -9143,18 +9143,22 @@ void Item_ref::update_used_tables() } -table_map Item_direct_view_ref::used_tables() const +table_map Item_direct_view_ref::used_tables() const { - return get_depended_from() ? + return get_depended_from() ? OUTER_REF_TABLE_BIT : - (view->merged ? (*ref)->used_tables() : view->table->map); + ((view->merged || !view->table) ? + (*ref)->used_tables() : + view->table->map); } -table_map Item_direct_view_ref::not_null_tables() const +table_map Item_direct_view_ref::not_null_tables() const { - return get_depended_from() ? + return get_depended_from() ? 0 : - (view->merged ? (*ref)->not_null_tables() : view->table->map); + ((view->merged || !view->table) ? + (*ref)->not_null_tables() : + view->table->map); } /* diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 6dd329f8c77..9c5d251c728 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -7927,7 +7927,8 @@ bool setup_tables(THD *thd, Name_resolution_context *context, while ((table_list= ti++)) { TABLE *table= table_list->table; - table->pos_in_table_list= table_list; + if (table) + table->pos_in_table_list= table_list; if (first_select_table && table_list->top_table() == first_select_table) { @@ -7940,7 +7941,7 @@ bool setup_tables(THD *thd, Name_resolution_context *context, { table_list->jtbm_table_no= tablenr; } - else + else if (table) { table->pos_in_table_list= table_list; setup_table_map(table, table_list, tablenr); diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 3ce375190a7..84e88196f20 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -68,7 +68,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, if (mysql_handle_list_of_derived(thd->lex, table_list, DT_PREPARE)) DBUG_RETURN(TRUE); - if (!table_list->updatable) + if (!table_list->single_table_updatable()) { my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "DELETE"); DBUG_RETURN(TRUE); @@ -526,7 +526,8 @@ int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds) setup_conds(thd, table_list, select_lex->leaf_tables, conds) || setup_ftfuncs(select_lex)) DBUG_RETURN(TRUE); - if (!table_list->updatable || check_key_in_view(thd, table_list)) + if (!table_list->single_table_updatable() || + check_key_in_view(thd, table_list)) { my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "DELETE"); DBUG_RETURN(TRUE); @@ -622,7 +623,7 @@ int mysql_multi_delete_prepare(THD *thd) DBUG_RETURN(TRUE); } - if (!target_tbl->correspondent_table->updatable || + if (!target_tbl->correspondent_table->single_table_updatable() || check_key_in_view(thd, target_tbl->correspondent_table)) { my_error(ER_NON_UPDATABLE_TABLE, MYF(0), diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 0955f9c0982..02a26254336 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -483,7 +483,7 @@ bool mysql_derived_merge_for_insert(THD *thd, LEX *lex, TABLE_LIST *derived) return mysql_derived_prepare(thd, lex, derived); if (!derived->is_multitable()) { - if (!derived->updatable) + if (!derived->single_table_updatable()) return derived->create_field_translation(thd); if (derived->merge_underlying_list) { diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index d01a594708e..a4943d5e13a 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -103,7 +103,8 @@ static bool check_view_insertability(THD *thd, TABLE_LIST *view); */ bool check_view_single_update(List<Item> &fields, List<Item> *values, - TABLE_LIST *view, table_map *map) + TABLE_LIST *view, table_map *map, + bool insert) { /* it is join view => we need to find the table for update */ List_iterator_fast<Item> it(fields); @@ -140,6 +141,14 @@ bool check_view_single_update(List<Item> &fields, List<Item> *values, */ tbl->table->insert_values= view->table->insert_values; view->table= tbl->table; + if (!tbl->single_table_updatable()) + { + if (insert) + my_error(ER_NON_INSERTABLE_TABLE, MYF(0), view->alias, "INSERT"); + else + my_error(ER_NON_UPDATABLE_TABLE, MYF(0), view->alias, "UPDATE"); + return TRUE; + } *map= tables; return FALSE; @@ -184,7 +193,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, { TABLE *table= table_list->table; - if (!table_list->updatable) + if (!table_list->single_table_updatable()) { my_error(ER_NON_INSERTABLE_TABLE, MYF(0), table_list->alias, "INSERT"); return -1; @@ -260,7 +269,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, if (check_view_single_update(fields, fields_and_values_from_different_maps ? (List<Item>*) 0 : &values, - table_list, map)) + table_list, map, true)) return -1; table= table_list->table; } @@ -347,7 +356,7 @@ static int check_update_fields(THD *thd, TABLE_LIST *insert_table_list, if (insert_table_list->is_view() && insert_table_list->is_merged_derived() && check_view_single_update(update_fields, &update_values, - insert_table_list, map)) + insert_table_list, map, false)) return -1; if (table->timestamp_field) @@ -1159,7 +1168,7 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list, bool insert_into_view= (table_list->view != 0); DBUG_ENTER("mysql_prepare_insert_check_table"); - if (!table_list->updatable) + if (!table_list->single_table_updatable()) { my_error(ER_NON_INSERTABLE_TABLE, MYF(0), table_list->alias, "INSERT"); DBUG_RETURN(TRUE); diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 42a8f001c6f..7fcb52a7b9c 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -187,7 +187,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, INSERT_ACL | UPDATE_ACL, FALSE)) DBUG_RETURN(-1); if (!table_list->table || // do not suport join view - !table_list->updatable || // and derived tables + !table_list->single_table_updatable() || // and derived tables check_key_in_view(thd, table_list)) { my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "LOAD"); diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 611c8ddf944..32ce8dc6fc4 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1274,7 +1274,7 @@ static int mysql_test_update(Prepared_statement *stmt, if (table_list->handle_derived(thd->lex, DT_PREPARE)) goto error; - if (!table_list->updatable) + if (!table_list->single_table_updatable()) { my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "UPDATE"); goto error; @@ -1348,7 +1348,7 @@ static bool mysql_test_delete(Prepared_statement *stmt, if (mysql_handle_derived(thd->lex, DT_PREPARE)) goto error; - if (!table_list->updatable) + if (!table_list->single_table_updatable()) { my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "DELETE"); goto error; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 80eb823c346..a921a87884e 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -257,7 +257,7 @@ int mysql_update(THD *thd, thd_proc_info(thd, "init"); table= table_list->table; - if (!table_list->updatable) + if (!table_list->single_table_updatable()) { my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "UPDATE"); DBUG_RETURN(1); @@ -1090,7 +1090,7 @@ reopen_tables: /* if table will be updated then check that it is unique */ if (table->map & tables_for_update) { - if (!tl->updatable || check_key_in_view(thd, tl)) + if (!tl->single_table_updatable() || check_key_in_view(thd, tl)) { my_error(ER_NON_UPDATABLE_TABLE, MYF(0), tl->alias, "UPDATE"); DBUG_RETURN(TRUE); diff --git a/sql/table.cc b/sql/table.cc index 5fe2d8afc42..f1ff353a8c4 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -3712,6 +3712,28 @@ bool TABLE_LIST::prep_where(THD *thd, Item **conds, DBUG_RETURN(FALSE); } +/** + Check that table/view is updatable and if it has single + underlying tables/views it is also updatable + + @return Result of the check. +*/ + +bool TABLE_LIST::single_table_updatable() +{ + if (!updatable) + return false; + if (view_tables && view_tables->elements == 1) + { + /* + We need to check deeply only single table views. Multi-table views + will be turned to multi-table updates and then checked by leaf tables + */ + return view_tables->head()->single_table_updatable(); + } + return true; +} + /* Merge ON expressions for a view @@ -5188,6 +5210,9 @@ void st_table::mark_virtual_columns_for_write(bool insert_fl) if (!vfield) return; + if (!vfield) + return; + for (vfield_ptr= vfield; *vfield_ptr; vfield_ptr++) { tmp_vfield= *vfield_ptr; diff --git a/sql/table.h b/sql/table.h index 376aa9824dc..09230e40f7a 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1797,6 +1797,9 @@ struct TABLE_LIST int fetch_number_of_rows(); bool change_refs_to_fields(); + + bool single_table_updatable(); + private: bool prep_check_option(THD *thd, uint8 check_opt_type); bool prep_where(THD *thd, Item **conds, bool no_where_clause); |