mirror of
https://github.com/MariaDB/server.git
synced 2025-01-18 04:53:01 +01:00
some small changes for MULTI-TABLE updates and other little fixes
This commit is contained in:
parent
74deec5a00
commit
d71bd75fca
3 changed files with 70 additions and 88 deletions
|
@ -684,7 +684,7 @@ public:
|
|||
enum enum_duplicates dupl;
|
||||
uint num_of_tables, num_fields, num_updated, *save_time_stamps, *field_sequence;
|
||||
int error;
|
||||
bool do_update;
|
||||
bool do_update, not_trans_safe;
|
||||
public:
|
||||
multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs,
|
||||
enum enum_duplicates handle_duplicates,
|
||||
|
|
124
sql/sql_parse.cc
124
sql/sql_parse.cc
|
@ -1224,8 +1224,6 @@ mysql_execute_command(void)
|
|||
(table_rules_on && tables && thd->slave_thread &&
|
||||
!tables_ok(thd,tables)))
|
||||
DBUG_VOID_RETURN;
|
||||
if (lex->sql_command==SQLCOM_UPDATE && select_lex->table_list.elements > 1)
|
||||
lex->sql_command=SQLCOM_MULTI_UPDATE;
|
||||
|
||||
thread_safe_increment(com_stat[lex->sql_command],&LOCK_thread_count);
|
||||
switch (lex->sql_command) {
|
||||
|
@ -1697,19 +1695,68 @@ mysql_execute_command(void)
|
|||
send_error(&thd->net,ER_WRONG_VALUE_COUNT);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
res = mysql_update(thd,tables,
|
||||
select_lex->item_list,
|
||||
lex->value_list,
|
||||
select_lex->where,
|
||||
(ORDER *) select_lex->order_list.first,
|
||||
select_lex->select_limit,
|
||||
lex->duplicates,
|
||||
lex->lock_option);
|
||||
if (select_lex->table_list.elements == 1)
|
||||
{
|
||||
res = mysql_update(thd,tables,
|
||||
select_lex->item_list,
|
||||
lex->value_list,
|
||||
select_lex->where,
|
||||
(ORDER *) select_lex->order_list.first,
|
||||
select_lex->select_limit,
|
||||
lex->duplicates,
|
||||
lex->lock_option);
|
||||
|
||||
#ifdef DELETE_ITEMS
|
||||
delete select_lex->where;
|
||||
delete select_lex->where;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
multi_update *result;
|
||||
uint table_count;
|
||||
TABLE_LIST *auxi;
|
||||
lex->sql_command=SQLCOM_MULTI_UPDATE;
|
||||
for (auxi=(TABLE_LIST*) tables, table_count=0 ; auxi ; auxi=auxi->next)
|
||||
{
|
||||
table_count++;
|
||||
auxi->lock_type=TL_WRITE;
|
||||
}
|
||||
if (select_lex->order_list.elements || (select_lex->select_limit && select_lex->select_limit < INT_MAX))
|
||||
{
|
||||
send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /// will have to come up with something better eventually
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege);
|
||||
if ((res=open_and_lock_tables(thd,tables)))
|
||||
break;
|
||||
if (!setup_fields(thd,tables,select_lex->item_list,1,0,0) &&
|
||||
!setup_fields(thd,tables,lex->value_list,0,0,0) && ! thd->fatal_error &&
|
||||
(result=new multi_update(thd,tables,select_lex->item_list,lex->duplicates,
|
||||
lex->lock_option, table_count)))
|
||||
{
|
||||
List <Item> total_list;
|
||||
List_iterator <Item> field_list(select_lex->item_list);
|
||||
List_iterator <Item> value_list(lex->value_list);
|
||||
Item *item;
|
||||
while ((item=field_list++))
|
||||
total_list.push_back(item);
|
||||
while ((item=value_list++))
|
||||
total_list.push_back(item);
|
||||
|
||||
res=mysql_select(thd,tables,total_list,
|
||||
select_lex->where,
|
||||
(ORDER *)NULL,(ORDER *)NULL,(Item *)NULL,
|
||||
(ORDER *)NULL,
|
||||
select_lex->options | thd->options |
|
||||
SELECT_NO_JOIN_CACHE,
|
||||
result);
|
||||
delete result;
|
||||
}
|
||||
else
|
||||
res= -1; // Error is not sent
|
||||
close_thread_tables(thd);
|
||||
}
|
||||
break;
|
||||
case SQLCOM_INSERT:
|
||||
if (check_access(thd,INSERT_ACL,tables->db,&tables->grant.privilege))
|
||||
goto error; /* purecov: inspected */
|
||||
|
@ -1879,59 +1926,6 @@ mysql_execute_command(void)
|
|||
close_thread_tables(thd);
|
||||
break;
|
||||
}
|
||||
case SQLCOM_MULTI_UPDATE:
|
||||
multi_update *result;
|
||||
uint table_count;
|
||||
TABLE_LIST *auxi;
|
||||
if (check_access(thd,UPDATE_ACL,tables->db,&tables->grant.privilege))
|
||||
goto error;
|
||||
if (grant_option && check_grant(thd,UPDATE_ACL,tables))
|
||||
goto error;
|
||||
if (select_lex->item_list.elements != lex->value_list.elements)
|
||||
{
|
||||
send_error(&thd->net,ER_WRONG_VALUE_COUNT);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
for (auxi=(TABLE_LIST*) tables, table_count=0 ; auxi ; auxi=auxi->next)
|
||||
{
|
||||
table_count++;
|
||||
auxi->lock_type=TL_WRITE;
|
||||
}
|
||||
if (select_lex->order_list.elements || (select_lex->select_limit && select_lex->select_limit < INT_MAX))
|
||||
{
|
||||
send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /// will have to come up with something better eventually
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege);
|
||||
if ((res=open_and_lock_tables(thd,tables)))
|
||||
break;
|
||||
if (!setup_fields(thd,tables,select_lex->item_list,1,0,0) &&
|
||||
!setup_fields(thd,tables,lex->value_list,0,0,0) && ! thd->fatal_error &&
|
||||
(result=new multi_update(thd,tables,select_lex->item_list,lex->duplicates,
|
||||
lex->lock_option, table_count)))
|
||||
{
|
||||
List <Item> total_list;
|
||||
List_iterator <Item> field_list(select_lex->item_list);
|
||||
List_iterator <Item> value_list(lex->value_list);
|
||||
Item *item;
|
||||
while ((item=field_list++))
|
||||
total_list.push_back(item);
|
||||
while ((item=value_list++))
|
||||
total_list.push_back(item);
|
||||
|
||||
res=mysql_select(thd,tables,total_list,
|
||||
select_lex->where,
|
||||
(ORDER *)NULL,(ORDER *)NULL,(Item *)NULL,
|
||||
(ORDER *)NULL,
|
||||
select_lex->options | thd->options |
|
||||
SELECT_NO_JOIN_CACHE,
|
||||
result);
|
||||
delete result;
|
||||
}
|
||||
else
|
||||
res= -1; // Error is not sent
|
||||
close_thread_tables(thd);
|
||||
break;
|
||||
case SQLCOM_DROP_TABLE:
|
||||
{
|
||||
if (check_table_access(thd,DROP_ACL,tables))
|
||||
|
|
|
@ -359,6 +359,7 @@ multi_update::multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs,
|
|||
tmp_tables = (TABLE **)NULL;
|
||||
int counter=0;
|
||||
ulong timestamp_query_id;
|
||||
not_trans_safe=false;
|
||||
for (TABLE_LIST *dt=ut ; dt ; dt=dt->next,counter++)
|
||||
{
|
||||
TABLE *table=ut->table;
|
||||
|
@ -420,6 +421,9 @@ multi_update::prepare(List<Item> &values)
|
|||
{
|
||||
num_updated++;
|
||||
table_ref->shared=1;
|
||||
if (!not_trans_safe && !table_ref->table->file->has_transactions())
|
||||
not_trans_safe=true;
|
||||
table_ref->table->no_keyread=1; // to be moved if initialize_tables has to be used
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -529,6 +533,7 @@ multi_update::~multi_update()
|
|||
{
|
||||
TABLE *table=table_being_updated->table;
|
||||
(void)table->file->extra(HA_EXTRA_READCHECK);
|
||||
table->no_keyread=0;
|
||||
if (error)
|
||||
table->time_stamp=save_time_stamps[counter];
|
||||
}
|
||||
|
@ -629,27 +634,13 @@ bool multi_update::send_data(List<Item> &values)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Return true if some table is not transaction safe */
|
||||
|
||||
static bool some_table_is_not_transaction_safe (TABLE_LIST *tl)
|
||||
{
|
||||
for (; tl ; tl=tl->next)
|
||||
{
|
||||
if (!(tl->table->file->has_transactions()))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void multi_update::send_error(uint errcode,const char *err)
|
||||
{
|
||||
/* First send error what ever it is ... */
|
||||
::send_error(&thd->net,errcode,err);
|
||||
|
||||
/* reset used flags */
|
||||
update_tables->table->no_keyread=0;
|
||||
// update_tables->table->no_keyread=0;
|
||||
|
||||
/* If nothing updated return */
|
||||
if (!updated)
|
||||
|
@ -665,8 +656,7 @@ void multi_update::send_error(uint errcode,const char *err)
|
|||
In all other cases do attempt updates ...
|
||||
*/
|
||||
if ((table_being_updated->table->file->has_transactions() &&
|
||||
table_being_updated == update_tables) ||
|
||||
!some_table_is_not_transaction_safe(update_tables->next))
|
||||
table_being_updated == update_tables) || !not_trans_safe)
|
||||
ha_rollback_stmt(thd);
|
||||
else if (do_update)
|
||||
VOID(do_updates(true));
|
||||
|
@ -721,7 +711,6 @@ int multi_update::do_updates (bool from_send_error)
|
|||
error = tmp_table->file->rnd_init(1);
|
||||
if (error)
|
||||
return error;
|
||||
bool not_trans_safe = some_table_is_not_transaction_safe(update_tables);
|
||||
while (!(error=tmp_table->file->rnd_next(tmp_table->record[0])) &&
|
||||
(!thd->killed || from_send_error || not_trans_safe))
|
||||
{
|
||||
|
@ -756,7 +745,7 @@ bool multi_update::send_eof()
|
|||
int error = do_updates(false); /* do_updates returns 0 if success */
|
||||
|
||||
/* reset used flags */
|
||||
update_tables->table->no_keyread=0;
|
||||
// update_tables->table->no_keyread=0;
|
||||
if (error == -1) error = 0;
|
||||
thd->proc_info="end";
|
||||
if (error)
|
||||
|
@ -767,8 +756,7 @@ bool multi_update::send_eof()
|
|||
was a non-transaction-safe table involved, since
|
||||
modifications in it cannot be rolled back. */
|
||||
|
||||
if (updated &&
|
||||
(!error || some_table_is_not_transaction_safe(update_tables)))
|
||||
if (updated || not_trans_safe)
|
||||
{
|
||||
mysql_update_log.write(thd,thd->query,thd->query_length);
|
||||
Query_log_event qinfo(thd, thd->query);
|
||||
|
@ -777,7 +765,7 @@ bool multi_update::send_eof()
|
|||
is not used */
|
||||
|
||||
if (mysql_bin_log.is_open() && mysql_bin_log.write(&qinfo) &&
|
||||
!some_table_is_not_transaction_safe(update_tables))
|
||||
!not_trans_safe)
|
||||
error=1; /* Log write failed: roll back
|
||||
the SQL statement */
|
||||
|
||||
|
|
Loading…
Reference in a new issue