1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00
This commit is contained in:
bell@sanja.is.com.ua
2004-11-11 21:18:10 +02:00
51 changed files with 1256 additions and 268 deletions

View File

@ -86,6 +86,28 @@ static bool check_fields(THD *thd, List<Item> &items)
}
/*
Process usual UPDATE
SYNOPSIS
mysql_update()
thd thread handler
fields fields for update
values values of fields for update
conds WHERE clause expression
order_num number of elemen in ORDER BY clause
order ORDER BY clause list
limit limit clause
handle_duplicates how to handle duplicates
RETURN
0 - OK
2 - privilege check and openning table passed, but we need to convert to
multi-update because of view substitution
1 - error and error sent to client
-1 - error and error is not sent to client
*/
int mysql_update(THD *thd,
TABLE_LIST *table_list,
List<Item> &fields,
@ -118,6 +140,15 @@ int mysql_update(THD *thd,
if ((error= open_and_lock_tables(thd, table_list)))
DBUG_RETURN(error);
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"));
/* convert to multiupdate */
return 2;
}
thd->proc_info="init";
table= table_list->table;
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
@ -520,8 +551,8 @@ int mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
tables.table= table;
tables.alias= table_list->alias;
if (setup_tables(thd, table_list, conds) ||
setup_conds(thd, table_list, conds) ||
if (setup_tables(thd, table_list, conds, &select_lex->leaf_tables, 0) ||
setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
select_lex->setup_ref_array(thd, order_num) ||
setup_order(thd, select_lex->ref_pointer_array,
table_list, all_fields, all_fields, order) ||
@ -579,6 +610,7 @@ int mysql_multi_update_prepare(THD *thd)
TABLE_LIST *table_list= lex->query_tables;
List<Item> *fields= &lex->select_lex.item_list;
TABLE_LIST *tl;
TABLE_LIST *leaves;
table_map tables_for_update;
int res;
bool update_view= 0;
@ -590,21 +622,25 @@ int mysql_multi_update_prepare(THD *thd)
if (open_tables(thd, table_list, & table_count) ||
mysql_handle_derived(lex, &mysql_derived_prepare))
DBUG_RETURN(thd->net.report_error ? -1 : 1);
if (setup_tables(thd, table_list, &lex->select_lex.where,
&lex->select_lex.leaf_tables, 0))
DBUG_RETURN(-1);
/*
Ensure that we have update privilege for all tables and columns in the
SET part
*/
for (tl= table_list; tl; tl= tl->next_local)
for (tl= (leaves= lex->select_lex.leaf_tables); tl; tl= tl->next_leaf)
{
TABLE *table= tl->table;
/*
Update of derived tables is checked later
We don't check privileges here, becasue then we would get error
"UPDATE command denided .. for column N" instead of
"Target table ... is not updatable"
*/
if (!tl->derived)
tl->grant.want_privilege= table->grant.want_privilege=
TABLE *table= tl->table;
TABLE_LIST *tlist;
if (!(tlist= tl->belong_to_view?tl->belong_to_view:tl)->derived)
tlist->grant.want_privilege= table->grant.want_privilege=
(UPDATE_ACL & ~table->grant.privilege);
}
@ -613,8 +649,7 @@ int mysql_multi_update_prepare(THD *thd)
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.no_wrap_view_item= 1,
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,
res))
@ -639,16 +674,8 @@ int mysql_multi_update_prepare(THD *thd)
/*
Setup timestamp handling and locking mode
*/
for (tl= table_list; tl ; tl= tl->next_local)
{
TABLE *table= tl->table;
for (tl= leaves; tl; tl= tl->next_leaf)
/* We only need SELECT privilege for columns in the values list */
tl->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 */
@ -738,16 +765,19 @@ int mysql_multi_update(THD *thd,
COND *conds,
ulong options,
enum enum_duplicates handle_duplicates,
SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex)
SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex,
bool converted)
{
int res;
int res= 0;
multi_update *result;
DBUG_ENTER("mysql_multi_update");
if ((res= mysql_multi_update_prepare(thd)))
DBUG_RETURN(res);
if (!(result= new multi_update(thd, table_list, fields, values,
if (!(result= new multi_update(thd, table_list,
thd->lex->select_lex.leaf_tables,
fields, values,
handle_duplicates)))
DBUG_RETURN(-1);
@ -771,12 +801,14 @@ int mysql_multi_update(THD *thd,
multi_update::multi_update(THD *thd_arg, TABLE_LIST *table_list,
TABLE_LIST *leaves_list,
List<Item> *field_list, List<Item> *value_list,
enum enum_duplicates handle_duplicates_arg)
:all_tables(table_list), update_tables(0), thd(thd_arg), tmp_tables(0),
updated(0), found(0), fields(field_list), values(value_list),
table_count(0), copy_field(0), handle_duplicates(handle_duplicates_arg),
do_update(1), trans_safe(0), transactional_tables(1)
:all_tables(table_list), leaves(leaves_list), update_tables(0),
thd(thd_arg), tmp_tables(0), updated(0), found(0), fields(field_list),
values(value_list), table_count(0), copy_field(0),
handle_duplicates(handle_duplicates_arg), do_update(1), trans_safe(0),
transactional_tables(1)
{}
@ -823,8 +855,9 @@ int multi_update::prepare(List<Item> &not_used_values,
*/
update.empty();
for (table_ref= all_tables; table_ref; table_ref= table_ref->next_local)
for (table_ref= leaves; table_ref; table_ref= table_ref->next_leaf)
{
/* TODO: add support of view of join support */
TABLE *table=table_ref->table;
if (tables_to_update & table->map)
{
@ -891,10 +924,10 @@ int multi_update::prepare(List<Item> &not_used_values,
which will cause an error when reading a row.
(This issue is mostly relevent for MyISAM tables)
*/
for (table_ref= all_tables; table_ref; table_ref= table_ref->next_local)
for (table_ref= leaves; table_ref; table_ref= table_ref->next_leaf)
{
TABLE *table=table_ref->table;
if (!(tables_to_update & table->map) &&
if (!(tables_to_update & table->map) &&
find_table_in_local_list(update_tables, table_ref->db,
table_ref->real_name))
table->no_cache= 1; // Disable row cache