mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 02:05:57 +01:00
post merge
This commit is contained in:
parent
3bc1fcd409
commit
c9497e2365
11 changed files with 96 additions and 55 deletions
|
@ -2670,11 +2670,6 @@ void Item_ref::cleanup()
|
|||
DBUG_ENTER("Item_ref::cleanup");
|
||||
Item_ident::cleanup();
|
||||
result_field= 0;
|
||||
DBUG_PRINT("info", ("hook: 0x%lx(0x%lx) original item: 0x%lx",
|
||||
(ulong)hook_ptr, (ulong)(hook_ptr?*hook_ptr:0),
|
||||
(ulong)orig_item));
|
||||
if (hook_ptr)
|
||||
*hook_ptr= orig_item;
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
|
|
@ -619,8 +619,7 @@ int mysql_multi_update(THD *thd, TABLE_LIST *table_list,
|
|||
List<Item> *fields, List<Item> *values,
|
||||
COND *conds, ulong options,
|
||||
enum enum_duplicates handle_duplicates,
|
||||
SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex,
|
||||
bool converted);
|
||||
SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex);
|
||||
int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
|
||||
List<Item> &fields, List_item *values,
|
||||
List<Item> &update_fields,
|
||||
|
@ -661,7 +660,8 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list,
|
|||
uint length, Item **ref,
|
||||
bool check_grants_table, bool check_grants_view,
|
||||
bool allow_rowid,
|
||||
uint *cached_field_index_ptr);
|
||||
uint *cached_field_index_ptr,
|
||||
bool register_tree_change);
|
||||
Field *
|
||||
find_field_in_real_table(THD *thd, TABLE *table, const char *name,
|
||||
uint length, bool check_grants, bool allow_rowid,
|
||||
|
|
|
@ -2360,7 +2360,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
|
|||
if (!find_field_in_table(thd, table_list, column->column.ptr(),
|
||||
column->column.ptr(),
|
||||
column->column.length(), 0, 0, 0, 0,
|
||||
&unused_field_idx))
|
||||
&unused_field_idx, FALSE))
|
||||
{
|
||||
my_error(ER_BAD_FIELD_ERROR, MYF(0),
|
||||
column->column.c_ptr(), table_list->alias);
|
||||
|
|
|
@ -2069,6 +2069,8 @@ const Field *view_ref_found= (Field*) 0x2;
|
|||
allow_rowid do allow finding of "_rowid" field?
|
||||
cached_field_index_ptr cached position in field list (used to
|
||||
speedup prepared tables field finding)
|
||||
register_tree_change TRUE if ref is not stack variable and we
|
||||
need register changes in item tree
|
||||
|
||||
RETURN
|
||||
0 field is not found
|
||||
|
@ -2082,7 +2084,8 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list,
|
|||
uint length, Item **ref,
|
||||
bool check_grants_table, bool check_grants_view,
|
||||
bool allow_rowid,
|
||||
uint *cached_field_index_ptr)
|
||||
uint *cached_field_index_ptr,
|
||||
bool register_tree_change)
|
||||
{
|
||||
DBUG_ENTER("find_field_in_table");
|
||||
DBUG_PRINT("enter", ("table:%s name: %s item name %s, ref 0x%lx",
|
||||
|
@ -2109,10 +2112,11 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list,
|
|||
*ref= trans[i].item;
|
||||
else
|
||||
{
|
||||
Item_ref *item_ref= new Item_ref(trans[i].item, table_list->view_name.str,
|
||||
Item_ref *item_ref= new Item_ref(&trans[i].item,
|
||||
table_list->view_name.str,
|
||||
item_name);
|
||||
/* as far as Item_ref have defined reference it do not need tables */
|
||||
if (item_ref)
|
||||
if (register_tree_change && item_ref)
|
||||
{
|
||||
thd->change_item_tree(ref, item_ref);
|
||||
(*ref)->fix_fields(thd, 0, ref);
|
||||
|
@ -2288,7 +2292,8 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
|
|||
check_privileges),
|
||||
(test(table->grant.want_privilege) &&
|
||||
check_privileges),
|
||||
1, &(item->cached_field_index));
|
||||
1, &(item->cached_field_index),
|
||||
TRUE);
|
||||
}
|
||||
if (found)
|
||||
{
|
||||
|
@ -2327,7 +2332,8 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
|
|||
check_privileges),
|
||||
(test(tables->grant.want_privilege) &&
|
||||
check_privileges),
|
||||
1, &(item->cached_field_index));
|
||||
1, &(item->cached_field_index),
|
||||
TRUE);
|
||||
if (find)
|
||||
{
|
||||
item->cached_table= tables;
|
||||
|
@ -2392,7 +2398,9 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
|
|||
check_privileges),
|
||||
(test(tables->grant.want_privilege) &&
|
||||
check_privileges),
|
||||
allow_rowid, &(item->cached_field_index));
|
||||
allow_rowid,
|
||||
&(item->cached_field_index),
|
||||
TRUE);
|
||||
if (field)
|
||||
{
|
||||
if (field == WRONG_GRANT)
|
||||
|
@ -3028,7 +3036,7 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
|
|||
!find_field_in_table(thd, natural_join_table, field_name,
|
||||
field_name,
|
||||
strlen(field_name), ¬_used_item, 0, 0, 0,
|
||||
¬_used_field_index))
|
||||
¬_used_field_index, TRUE))
|
||||
{
|
||||
Item *item= iterator->item(thd);
|
||||
if (!found++)
|
||||
|
@ -3037,7 +3045,7 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
|
|||
it->after(item);
|
||||
if (view && !thd->lex->current_select->no_wrap_view_item)
|
||||
{
|
||||
item= new Item_ref(it->ref(), NULL, tables->view_name.str,
|
||||
item= new Item_ref(it->ref(), tables->view_name.str,
|
||||
field_name);
|
||||
}
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
|
@ -3252,7 +3260,8 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds)
|
|||
t1_field_name,
|
||||
strlen(t1_field_name), &item_t2,
|
||||
0, 0, 0,
|
||||
¬_used_field_index)))
|
||||
¬_used_field_index,
|
||||
FALSE)))
|
||||
{
|
||||
if (t2_field != view_ref_found)
|
||||
{
|
||||
|
@ -3262,13 +3271,6 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds)
|
|||
t2_field->query_id= thd->query_id;
|
||||
t2->used_keys.intersect(t2_field->part_of_key);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBUG_ASSERT(t2_field == view_ref_found &&
|
||||
item_t2->type() == Item::REF_ITEM);
|
||||
/* remove hooking to stack variable */
|
||||
((Item_ref*) item_t2)->hook_ptr= 0;
|
||||
}
|
||||
if ((t1_field= iterator->field()))
|
||||
{
|
||||
/* Mark field used for table cache */
|
||||
|
|
|
@ -1781,7 +1781,7 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
|||
query
|
||||
*/
|
||||
if (!(thd->lex->current_select->options & OPTION_BUFFER_RESULT) &&
|
||||
unique_table(table_list, table_list->next_independent()))
|
||||
unique_table(table_list, table_list->next_global))
|
||||
{
|
||||
/* Using same table for INSERT and SELECT */
|
||||
thd->lex->current_select->options|= OPTION_BUFFER_RESULT;
|
||||
|
|
|
@ -150,7 +150,7 @@ void lex_start(THD *thd, uchar *buf,uint length)
|
|||
lex->found_colon= 0;
|
||||
lex->safe_to_cache_query= 1;
|
||||
lex->time_zone_tables_used= 0;
|
||||
lex->proc_table= lex->query_tables= 0;
|
||||
lex->leaf_tables_insert= lex->proc_table= lex->query_tables= 0;
|
||||
lex->query_tables_last= &lex->query_tables;
|
||||
lex->variables_used= 0;
|
||||
lex->select_lex.parent_lex= lex;
|
||||
|
|
|
@ -710,6 +710,7 @@ typedef struct st_lex
|
|||
uint grant, grant_tot_col, which_columns;
|
||||
uint fk_delete_opt, fk_update_opt, fk_match_option;
|
||||
uint slave_thd_opt;
|
||||
uint table_count; /* used when usual update transformed in multiupdate */
|
||||
uint8 describe;
|
||||
uint8 derived_tables;
|
||||
uint8 create_view_algorithm;
|
||||
|
|
|
@ -121,9 +121,12 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
|||
table_list->lock_type= lock_type;
|
||||
if ((res= open_and_lock_tables(thd, table_list)))
|
||||
DBUG_RETURN(res);
|
||||
if (setup_tables(thd, table_list, &unused_conds))
|
||||
if (setup_tables(thd, table_list, &unused_conds,
|
||||
&thd->lex->select_lex.leaf_tables, 0))
|
||||
DBUG_RETURN(-1);
|
||||
if (!table_list->updatable || check_key_in_view(thd, table_list))
|
||||
if (!table_list->table || // do not suport join view
|
||||
!table_list->updatable || // and derived tables
|
||||
check_key_in_view(thd, table_list))
|
||||
{
|
||||
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "LOAD");
|
||||
DBUG_RETURN(-1);
|
||||
|
|
|
@ -2801,7 +2801,6 @@ unsent_create_error:
|
|||
break;
|
||||
case SQLCOM_UPDATE_MULTI:
|
||||
{
|
||||
bool converted= 0;
|
||||
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
||||
if (res != 2)
|
||||
{
|
||||
|
@ -2809,17 +2808,14 @@ unsent_create_error:
|
|||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
res= 0;
|
||||
converted= 1;
|
||||
}
|
||||
|
||||
res= mysql_multi_update(thd, all_tables,
|
||||
&select_lex->item_list,
|
||||
&lex->value_list,
|
||||
select_lex->where,
|
||||
select_lex->options,
|
||||
lex->duplicates, unit, select_lex,
|
||||
converted);
|
||||
lex->duplicates, unit, select_lex);
|
||||
break;
|
||||
}
|
||||
case SQLCOM_REPLACE:
|
||||
|
|
|
@ -127,6 +127,7 @@ int mysql_update(THD *thd,
|
|||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
uint want_privilege;
|
||||
#endif
|
||||
uint table_count= 0;
|
||||
ulong query_id=thd->query_id, timestamp_query_id;
|
||||
ha_rows updated, found;
|
||||
key_map old_used_keys;
|
||||
|
@ -138,17 +139,26 @@ int mysql_update(THD *thd,
|
|||
LINT_INIT(used_index);
|
||||
LINT_INIT(timestamp_query_id);
|
||||
|
||||
if ((error= open_and_lock_tables(thd, table_list)))
|
||||
DBUG_RETURN(error);
|
||||
if (open_tables(thd, table_list, &table_count))
|
||||
DBUG_RETURN(thd->net.report_error ? -1 : 1);
|
||||
|
||||
if (table_list->table == 0)
|
||||
{
|
||||
DBUG_ASSERT(table_list->view &&
|
||||
table_list->ancestor && table_list->ancestor->next_local);
|
||||
DBUG_PRINT("info", ("Switch to multi-update"));
|
||||
/* pass counter value */
|
||||
thd->lex->table_count= table_count;
|
||||
/* convert to multiupdate */
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (lock_tables(thd, table_list, table_count) ||
|
||||
mysql_handle_derived(thd->lex, &mysql_derived_prepare) ||
|
||||
(thd->fill_derived_tables() &&
|
||||
mysql_handle_derived(thd->lex, &mysql_derived_filling)))
|
||||
DBUG_RETURN(thd->net.report_error ? -1 : 1);
|
||||
|
||||
thd->proc_info="init";
|
||||
table= table_list->table;
|
||||
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
|
||||
|
@ -614,14 +624,25 @@ int mysql_multi_update_prepare(THD *thd)
|
|||
table_map tables_for_update;
|
||||
int res;
|
||||
bool update_view= 0;
|
||||
uint table_count;
|
||||
/*
|
||||
if this multi-update was converted from usual update, here is table
|
||||
counter else junk will be assigned here, but then replaced with real
|
||||
count in open_tables()
|
||||
*/
|
||||
uint table_count= lex->table_count;
|
||||
const bool using_lock_tables= thd->locked_tables != 0;
|
||||
bool original_multiupdate= (thd->lex->sql_command == SQLCOM_UPDATE_MULTI);
|
||||
DBUG_ENTER("mysql_multi_update_prepare");
|
||||
|
||||
/* open tables and create derived ones, but do not lock and fill them */
|
||||
if (open_tables(thd, table_list, & table_count) ||
|
||||
if ((original_multiupdate && open_tables(thd, table_list, & table_count)) ||
|
||||
mysql_handle_derived(lex, &mysql_derived_prepare))
|
||||
DBUG_RETURN(thd->net.report_error ? -1 : 1);
|
||||
/*
|
||||
setup_tables() need for VIEWs. JOIN::prepare() will call setup_tables()
|
||||
second time, but this call will do nothing (there are check for second
|
||||
call in setup_tables()).
|
||||
*/
|
||||
if (setup_tables(thd, table_list, &lex->select_lex.where,
|
||||
&lex->select_lex.leaf_tables, 0))
|
||||
DBUG_RETURN(-1);
|
||||
|
@ -644,11 +665,6 @@ int mysql_multi_update_prepare(THD *thd)
|
|||
(UPDATE_ACL & ~table->grant.privilege);
|
||||
}
|
||||
|
||||
/*
|
||||
setup_tables() need for VIEWs. JOIN::prepare() will call setup_tables()
|
||||
second time, but this call will do nothing (there are check for second
|
||||
call in setup_tables()).
|
||||
*/
|
||||
if ((lex->select_lex.no_wrap_view_item= 1,
|
||||
res= setup_fields(thd, 0, table_list, *fields, 1, 0, 0),
|
||||
lex->select_lex.no_wrap_view_item= 0,
|
||||
|
@ -675,7 +691,16 @@ int mysql_multi_update_prepare(THD *thd)
|
|||
Setup timestamp handling and locking mode
|
||||
*/
|
||||
for (tl= leaves; tl; tl= tl->next_leaf)
|
||||
{
|
||||
TABLE *table= tl->table;
|
||||
TABLE_LIST *tlist= tl->belong_to_view?tl->belong_to_view:tl;
|
||||
|
||||
/* We only need SELECT privilege for columns in the values list */
|
||||
tlist->grant.want_privilege= table->grant.want_privilege=
|
||||
(SELECT_ACL & ~table->grant.privilege);
|
||||
/* Only set timestamp column if this is not modified */
|
||||
if (table->timestamp_field &&
|
||||
table->timestamp_field->query_id == thd->query_id)
|
||||
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
|
||||
|
||||
/* if table will be updated then check that it is unique */
|
||||
|
@ -711,6 +736,23 @@ int mysql_multi_update_prepare(THD *thd)
|
|||
tl->table->reginfo.lock_type= tl->lock_type;
|
||||
}
|
||||
|
||||
/* check single table update for view compound from several tables */
|
||||
for (tl= table_list; tl; tl= tl->next_local)
|
||||
{
|
||||
if (tl->table == 0)
|
||||
{
|
||||
DBUG_ASSERT(tl->view &&
|
||||
tl->ancestor && tl->ancestor->next_local);
|
||||
TABLE_LIST *for_update= 0;
|
||||
if (tl->check_single_table(&for_update, tables_for_update))
|
||||
{
|
||||
my_error(ER_VIEW_MULTIUPDATE, MYF(0),
|
||||
tl->view_db.str, tl->view_name.str);
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
opened_tables= thd->status_var.opened_tables;
|
||||
/* now lock and fill tables */
|
||||
if (lock_tables(thd, table_list, table_count))
|
||||
|
@ -740,7 +782,8 @@ int mysql_multi_update_prepare(THD *thd)
|
|||
/* undone setup_tables() */
|
||||
table_list->setup_is_done= 0;
|
||||
|
||||
if (setup_tables(thd, table_list, &lex->select_lex.where) ||
|
||||
if (setup_tables(thd, table_list, &lex->select_lex.where,
|
||||
&lex->select_lex.leaf_tables, 0) ||
|
||||
(lex->select_lex.no_wrap_view_item= 1,
|
||||
res= setup_fields(thd, 0, table_list, *fields, 1, 0, 0),
|
||||
lex->select_lex.no_wrap_view_item= 0,
|
||||
|
@ -765,8 +808,7 @@ int mysql_multi_update(THD *thd,
|
|||
COND *conds,
|
||||
ulong options,
|
||||
enum enum_duplicates handle_duplicates,
|
||||
SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex,
|
||||
bool converted)
|
||||
SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex)
|
||||
{
|
||||
int res= 0;
|
||||
multi_update *result;
|
||||
|
|
18
sql/table.cc
18
sql/table.cc
|
@ -1841,9 +1841,10 @@ void st_table_list::cleanup_items()
|
|||
if (!field_translation)
|
||||
return;
|
||||
|
||||
Item **end= field_translation + view->select_lex.item_list.elements;
|
||||
for (Item **item= field_translation; item < end; item++)
|
||||
(*item)->walk(&Item::cleanup_processor, 0);
|
||||
Field_translator *end= (field_translation +
|
||||
view->select_lex.item_list.elements);
|
||||
for (Field_translator *transl= field_translation; transl < end; transl++)
|
||||
transl->item->walk(&Item::cleanup_processor, 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1883,7 +1884,7 @@ int st_table_list::view_check_option(THD *thd, bool ignore_failure)
|
|||
|
||||
/*
|
||||
Find table in underlaying tables by mask and check that only this
|
||||
table sbelong to given mask
|
||||
table belong to given mask
|
||||
|
||||
SYNOPSIS
|
||||
st_table_list::check_single_table()
|
||||
|
@ -1893,8 +1894,8 @@ int st_table_list::view_check_option(THD *thd, bool ignore_failure)
|
|||
map bit mask of tables
|
||||
|
||||
RETURN
|
||||
0 table not found or found only one
|
||||
1 found several tables
|
||||
FALSE table not found or found only one
|
||||
TRUE found several tables
|
||||
*/
|
||||
|
||||
bool st_table_list::check_single_table(st_table_list **table, table_map map)
|
||||
|
@ -1906,15 +1907,16 @@ bool st_table_list::check_single_table(st_table_list **table, table_map map)
|
|||
if (tbl->table->map & map)
|
||||
{
|
||||
if (*table)
|
||||
return 1;
|
||||
return TRUE;
|
||||
else
|
||||
*table= tbl;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (tbl->check_single_table(table, map))
|
||||
return 1;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue