some small changes for MULTI-TABLE updates and other little fixes
sql/sql_class.h: small optimisations for MULTI-TABLE UPDATE's sql/sql_parse.cc: Could not look at that if () at the start of execute_command, and as Monty evidently did not have time, so I optimised it away in the best fashion I know of. sql/sql_update.cc: Some optimisations for MULTI-TABLE UPDATE's
This commit is contained in:
parent
84d3da1df8
commit
4d638f1e35
@ -684,7 +684,7 @@ public:
|
|||||||
enum enum_duplicates dupl;
|
enum enum_duplicates dupl;
|
||||||
uint num_of_tables, num_fields, num_updated, *save_time_stamps, *field_sequence;
|
uint num_of_tables, num_fields, num_updated, *save_time_stamps, *field_sequence;
|
||||||
int error;
|
int error;
|
||||||
bool do_update;
|
bool do_update, not_trans_safe;
|
||||||
public:
|
public:
|
||||||
multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs,
|
multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs,
|
||||||
enum enum_duplicates handle_duplicates,
|
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 &&
|
(table_rules_on && tables && thd->slave_thread &&
|
||||||
!tables_ok(thd,tables)))
|
!tables_ok(thd,tables)))
|
||||||
DBUG_VOID_RETURN;
|
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);
|
thread_safe_increment(com_stat[lex->sql_command],&LOCK_thread_count);
|
||||||
switch (lex->sql_command) {
|
switch (lex->sql_command) {
|
||||||
@ -1697,19 +1695,68 @@ mysql_execute_command(void)
|
|||||||
send_error(&thd->net,ER_WRONG_VALUE_COUNT);
|
send_error(&thd->net,ER_WRONG_VALUE_COUNT);
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
res = mysql_update(thd,tables,
|
if (select_lex->table_list.elements == 1)
|
||||||
select_lex->item_list,
|
{
|
||||||
lex->value_list,
|
res = mysql_update(thd,tables,
|
||||||
select_lex->where,
|
select_lex->item_list,
|
||||||
(ORDER *) select_lex->order_list.first,
|
lex->value_list,
|
||||||
select_lex->select_limit,
|
select_lex->where,
|
||||||
lex->duplicates,
|
(ORDER *) select_lex->order_list.first,
|
||||||
lex->lock_option);
|
select_lex->select_limit,
|
||||||
|
lex->duplicates,
|
||||||
|
lex->lock_option);
|
||||||
|
|
||||||
#ifdef DELETE_ITEMS
|
#ifdef DELETE_ITEMS
|
||||||
delete select_lex->where;
|
delete select_lex->where;
|
||||||
#endif
|
#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:
|
case SQLCOM_INSERT:
|
||||||
if (check_access(thd,INSERT_ACL,tables->db,&tables->grant.privilege))
|
if (check_access(thd,INSERT_ACL,tables->db,&tables->grant.privilege))
|
||||||
goto error; /* purecov: inspected */
|
goto error; /* purecov: inspected */
|
||||||
@ -1879,59 +1926,6 @@ mysql_execute_command(void)
|
|||||||
close_thread_tables(thd);
|
close_thread_tables(thd);
|
||||||
break;
|
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:
|
case SQLCOM_DROP_TABLE:
|
||||||
{
|
{
|
||||||
if (check_table_access(thd,DROP_ACL,tables))
|
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;
|
tmp_tables = (TABLE **)NULL;
|
||||||
int counter=0;
|
int counter=0;
|
||||||
ulong timestamp_query_id;
|
ulong timestamp_query_id;
|
||||||
|
not_trans_safe=false;
|
||||||
for (TABLE_LIST *dt=ut ; dt ; dt=dt->next,counter++)
|
for (TABLE_LIST *dt=ut ; dt ; dt=dt->next,counter++)
|
||||||
{
|
{
|
||||||
TABLE *table=ut->table;
|
TABLE *table=ut->table;
|
||||||
@ -420,6 +421,9 @@ multi_update::prepare(List<Item> &values)
|
|||||||
{
|
{
|
||||||
num_updated++;
|
num_updated++;
|
||||||
table_ref->shared=1;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -529,6 +533,7 @@ multi_update::~multi_update()
|
|||||||
{
|
{
|
||||||
TABLE *table=table_being_updated->table;
|
TABLE *table=table_being_updated->table;
|
||||||
(void)table->file->extra(HA_EXTRA_READCHECK);
|
(void)table->file->extra(HA_EXTRA_READCHECK);
|
||||||
|
table->no_keyread=0;
|
||||||
if (error)
|
if (error)
|
||||||
table->time_stamp=save_time_stamps[counter];
|
table->time_stamp=save_time_stamps[counter];
|
||||||
}
|
}
|
||||||
@ -629,27 +634,13 @@ bool multi_update::send_data(List<Item> &values)
|
|||||||
return 0;
|
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)
|
void multi_update::send_error(uint errcode,const char *err)
|
||||||
{
|
{
|
||||||
/* First send error what ever it is ... */
|
/* First send error what ever it is ... */
|
||||||
::send_error(&thd->net,errcode,err);
|
::send_error(&thd->net,errcode,err);
|
||||||
|
|
||||||
/* reset used flags */
|
/* reset used flags */
|
||||||
update_tables->table->no_keyread=0;
|
// update_tables->table->no_keyread=0;
|
||||||
|
|
||||||
/* If nothing updated return */
|
/* If nothing updated return */
|
||||||
if (!updated)
|
if (!updated)
|
||||||
@ -665,8 +656,7 @@ void multi_update::send_error(uint errcode,const char *err)
|
|||||||
In all other cases do attempt updates ...
|
In all other cases do attempt updates ...
|
||||||
*/
|
*/
|
||||||
if ((table_being_updated->table->file->has_transactions() &&
|
if ((table_being_updated->table->file->has_transactions() &&
|
||||||
table_being_updated == update_tables) ||
|
table_being_updated == update_tables) || !not_trans_safe)
|
||||||
!some_table_is_not_transaction_safe(update_tables->next))
|
|
||||||
ha_rollback_stmt(thd);
|
ha_rollback_stmt(thd);
|
||||||
else if (do_update)
|
else if (do_update)
|
||||||
VOID(do_updates(true));
|
VOID(do_updates(true));
|
||||||
@ -721,7 +711,6 @@ int multi_update::do_updates (bool from_send_error)
|
|||||||
error = tmp_table->file->rnd_init(1);
|
error = tmp_table->file->rnd_init(1);
|
||||||
if (error)
|
if (error)
|
||||||
return 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])) &&
|
while (!(error=tmp_table->file->rnd_next(tmp_table->record[0])) &&
|
||||||
(!thd->killed || from_send_error || not_trans_safe))
|
(!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 */
|
int error = do_updates(false); /* do_updates returns 0 if success */
|
||||||
|
|
||||||
/* reset used flags */
|
/* reset used flags */
|
||||||
update_tables->table->no_keyread=0;
|
// update_tables->table->no_keyread=0;
|
||||||
if (error == -1) error = 0;
|
if (error == -1) error = 0;
|
||||||
thd->proc_info="end";
|
thd->proc_info="end";
|
||||||
if (error)
|
if (error)
|
||||||
@ -767,8 +756,7 @@ bool multi_update::send_eof()
|
|||||||
was a non-transaction-safe table involved, since
|
was a non-transaction-safe table involved, since
|
||||||
modifications in it cannot be rolled back. */
|
modifications in it cannot be rolled back. */
|
||||||
|
|
||||||
if (updated &&
|
if (updated || not_trans_safe)
|
||||||
(!error || some_table_is_not_transaction_safe(update_tables)))
|
|
||||||
{
|
{
|
||||||
mysql_update_log.write(thd,thd->query,thd->query_length);
|
mysql_update_log.write(thd,thd->query,thd->query_length);
|
||||||
Query_log_event qinfo(thd, thd->query);
|
Query_log_event qinfo(thd, thd->query);
|
||||||
@ -777,7 +765,7 @@ bool multi_update::send_eof()
|
|||||||
is not used */
|
is not used */
|
||||||
|
|
||||||
if (mysql_bin_log.is_open() && mysql_bin_log.write(&qinfo) &&
|
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
|
error=1; /* Log write failed: roll back
|
||||||
the SQL statement */
|
the SQL statement */
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user