Merge bk-internal.mysql.com:/home/bk/mysql-5.1-runtime
into mockturtle.local:/home/dlenev/src/mysql-5.1-bg20670 mysql-test/r/trigger.result: Auto merged mysql-test/t/trigger.test: Auto merged sql/mysql_priv.h: Auto merged sql/opt_range.cc: Auto merged sql/opt_range.h: Auto merged sql/sql_partition.cc: Auto merged sql/sql_update.cc: Auto merged
This commit is contained in:
commit
72d698e8ed
@ -1173,4 +1173,16 @@ TRIGGER t2_bi BEFORE INSERT ON t2 FOR EACH ROW SET @a = 2;
|
|||||||
ERROR HY000: String '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY' is too long for host name (should be no longer than 60)
|
ERROR HY000: String '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY' is too long for host name (should be no longer than 60)
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
DROP TABLE t2;
|
DROP TABLE t2;
|
||||||
|
drop table if exists t1;
|
||||||
|
create table t1 (i int, j int key);
|
||||||
|
insert into t1 values (1,1), (2,2), (3,3);
|
||||||
|
create trigger t1_bu before update on t1 for each row
|
||||||
|
set new.j = new.j + 10;
|
||||||
|
update t1 set i= i+ 10 where j > 2;
|
||||||
|
select * from t1;
|
||||||
|
i j
|
||||||
|
1 1
|
||||||
|
2 2
|
||||||
|
13 13
|
||||||
|
drop table t1;
|
||||||
End of 5.0 tests
|
End of 5.0 tests
|
||||||
|
@ -1421,4 +1421,23 @@ DROP TABLE t1;
|
|||||||
DROP TABLE t2;
|
DROP TABLE t2;
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#20670 "UPDATE using key and invoking trigger that modifies
|
||||||
|
# this key does not stop"
|
||||||
|
#
|
||||||
|
|
||||||
|
--disable_warnings
|
||||||
|
drop table if exists t1;
|
||||||
|
--enable_warnings
|
||||||
|
create table t1 (i int, j int key);
|
||||||
|
insert into t1 values (1,1), (2,2), (3,3);
|
||||||
|
create trigger t1_bu before update on t1 for each row
|
||||||
|
set new.j = new.j + 10;
|
||||||
|
# This should not work indefinitely and should cause
|
||||||
|
# expected result
|
||||||
|
update t1 set i= i+ 10 where j > 2;
|
||||||
|
select * from t1;
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
|
||||||
--echo End of 5.0 tests
|
--echo End of 5.0 tests
|
||||||
|
44
sql/key.cc
44
sql/key.cc
@ -359,31 +359,29 @@ void key_unpack(String *to,TABLE *table,uint idx)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Return 1 if any field in a list is part of key or the key uses a field
|
Check if key uses field that is marked in passed field bitmap.
|
||||||
that is automaticly updated (like a timestamp)
|
|
||||||
|
SYNOPSIS
|
||||||
|
is_key_used()
|
||||||
|
table TABLE object with which keys and fields are associated.
|
||||||
|
idx Key to be checked.
|
||||||
|
fields Bitmap of fields to be checked.
|
||||||
|
|
||||||
|
NOTE
|
||||||
|
This function uses TABLE::tmp_set bitmap so the caller should care
|
||||||
|
about saving/restoring its state if it also uses this bitmap.
|
||||||
|
|
||||||
|
RETURN VALUE
|
||||||
|
TRUE Key uses field from bitmap
|
||||||
|
FALSE Otherwise
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool check_if_key_used(TABLE *table, uint idx, List<Item> &fields)
|
bool is_key_used(TABLE *table, uint idx, const MY_BITMAP *fields)
|
||||||
{
|
{
|
||||||
List_iterator_fast<Item> f(fields);
|
bitmap_clear_all(&table->tmp_set);
|
||||||
KEY_PART_INFO *key_part,*key_part_end;
|
table->mark_columns_used_by_index_no_reset(idx, &table->tmp_set);
|
||||||
for (key_part=table->key_info[idx].key_part,key_part_end=key_part+
|
if (bitmap_is_overlapping(&table->tmp_set, fields))
|
||||||
table->key_info[idx].key_parts ;
|
return 1;
|
||||||
key_part < key_part_end;
|
|
||||||
key_part++)
|
|
||||||
{
|
|
||||||
Item_field *field;
|
|
||||||
|
|
||||||
if (key_part->field == table->timestamp_field)
|
|
||||||
return 1; // Can't be used for update
|
|
||||||
|
|
||||||
f.rewind();
|
|
||||||
while ((field=(Item_field*) f++))
|
|
||||||
{
|
|
||||||
if (key_part->field->eq(field->field))
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
If table handler has primary key as part of the index, check that primary
|
If table handler has primary key as part of the index, check that primary
|
||||||
@ -391,7 +389,7 @@ bool check_if_key_used(TABLE *table, uint idx, List<Item> &fields)
|
|||||||
*/
|
*/
|
||||||
if (idx != table->s->primary_key && table->s->primary_key < MAX_KEY &&
|
if (idx != table->s->primary_key && table->s->primary_key < MAX_KEY &&
|
||||||
(table->file->ha_table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX))
|
(table->file->ha_table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX))
|
||||||
return check_if_key_used(table, table->s->primary_key, fields);
|
return is_key_used(table, table->s->primary_key, fields);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1417,7 +1417,7 @@ void key_restore(byte *to_record, byte *from_key, KEY *key_info,
|
|||||||
uint key_length);
|
uint key_length);
|
||||||
bool key_cmp_if_same(TABLE *form,const byte *key,uint index,uint key_length);
|
bool key_cmp_if_same(TABLE *form,const byte *key,uint index,uint key_length);
|
||||||
void key_unpack(String *to,TABLE *form,uint index);
|
void key_unpack(String *to,TABLE *form,uint index);
|
||||||
bool check_if_key_used(TABLE *table, uint idx, List<Item> &fields);
|
bool is_key_used(TABLE *table, uint idx, const MY_BITMAP *fields);
|
||||||
int key_cmp(KEY_PART_INFO *key_part, const byte *key, uint key_length);
|
int key_cmp(KEY_PART_INFO *key_part, const byte *key, uint key_length);
|
||||||
int key_rec_cmp(void *key_info, byte *a, byte *b);
|
int key_rec_cmp(void *key_info, byte *a, byte *b);
|
||||||
|
|
||||||
|
@ -7526,42 +7526,42 @@ static bool null_part_in_key(KEY_PART *key_part, const char *key, uint length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool QUICK_SELECT_I::check_if_keys_used(List<Item> *fields)
|
bool QUICK_SELECT_I::is_keys_used(const MY_BITMAP *fields)
|
||||||
{
|
{
|
||||||
return check_if_key_used(head, index, *fields);
|
return is_key_used(head, index, fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QUICK_INDEX_MERGE_SELECT::check_if_keys_used(List<Item> *fields)
|
bool QUICK_INDEX_MERGE_SELECT::is_keys_used(const MY_BITMAP *fields)
|
||||||
{
|
{
|
||||||
QUICK_RANGE_SELECT *quick;
|
QUICK_RANGE_SELECT *quick;
|
||||||
List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects);
|
List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects);
|
||||||
while ((quick= it++))
|
while ((quick= it++))
|
||||||
{
|
{
|
||||||
if (check_if_key_used(head, quick->index, *fields))
|
if (is_key_used(head, quick->index, fields))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QUICK_ROR_INTERSECT_SELECT::check_if_keys_used(List<Item> *fields)
|
bool QUICK_ROR_INTERSECT_SELECT::is_keys_used(const MY_BITMAP *fields)
|
||||||
{
|
{
|
||||||
QUICK_RANGE_SELECT *quick;
|
QUICK_RANGE_SELECT *quick;
|
||||||
List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects);
|
List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects);
|
||||||
while ((quick= it++))
|
while ((quick= it++))
|
||||||
{
|
{
|
||||||
if (check_if_key_used(head, quick->index, *fields))
|
if (is_key_used(head, quick->index, fields))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QUICK_ROR_UNION_SELECT::check_if_keys_used(List<Item> *fields)
|
bool QUICK_ROR_UNION_SELECT::is_keys_used(const MY_BITMAP *fields)
|
||||||
{
|
{
|
||||||
QUICK_SELECT_I *quick;
|
QUICK_SELECT_I *quick;
|
||||||
List_iterator_fast<QUICK_SELECT_I> it(quick_selects);
|
List_iterator_fast<QUICK_SELECT_I> it(quick_selects);
|
||||||
while ((quick= it++))
|
while ((quick= it++))
|
||||||
{
|
{
|
||||||
if (quick->check_if_keys_used(fields))
|
if (quick->is_keys_used(fields))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -224,10 +224,9 @@ public:
|
|||||||
virtual void add_info_string(String *str) {};
|
virtual void add_info_string(String *str) {};
|
||||||
/*
|
/*
|
||||||
Return 1 if any index used by this quick select
|
Return 1 if any index used by this quick select
|
||||||
a) uses field that is listed in passed field list or
|
uses field which is marked in passed bitmap.
|
||||||
b) is automatically updated (like a timestamp)
|
|
||||||
*/
|
*/
|
||||||
virtual bool check_if_keys_used(List<Item> *fields);
|
virtual bool is_keys_used(const MY_BITMAP *fields);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
rowid of last row retrieved by this quick select. This is used only when
|
rowid of last row retrieved by this quick select. This is used only when
|
||||||
@ -425,7 +424,7 @@ public:
|
|||||||
int get_type() { return QS_TYPE_INDEX_MERGE; }
|
int get_type() { return QS_TYPE_INDEX_MERGE; }
|
||||||
void add_keys_and_lengths(String *key_names, String *used_lengths);
|
void add_keys_and_lengths(String *key_names, String *used_lengths);
|
||||||
void add_info_string(String *str);
|
void add_info_string(String *str);
|
||||||
bool check_if_keys_used(List<Item> *fields);
|
bool is_keys_used(const MY_BITMAP *fields);
|
||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
void dbug_dump(int indent, bool verbose);
|
void dbug_dump(int indent, bool verbose);
|
||||||
#endif
|
#endif
|
||||||
@ -484,7 +483,7 @@ public:
|
|||||||
int get_type() { return QS_TYPE_ROR_INTERSECT; }
|
int get_type() { return QS_TYPE_ROR_INTERSECT; }
|
||||||
void add_keys_and_lengths(String *key_names, String *used_lengths);
|
void add_keys_and_lengths(String *key_names, String *used_lengths);
|
||||||
void add_info_string(String *str);
|
void add_info_string(String *str);
|
||||||
bool check_if_keys_used(List<Item> *fields);
|
bool is_keys_used(const MY_BITMAP *fields);
|
||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
void dbug_dump(int indent, bool verbose);
|
void dbug_dump(int indent, bool verbose);
|
||||||
#endif
|
#endif
|
||||||
@ -538,7 +537,7 @@ public:
|
|||||||
int get_type() { return QS_TYPE_ROR_UNION; }
|
int get_type() { return QS_TYPE_ROR_UNION; }
|
||||||
void add_keys_and_lengths(String *key_names, String *used_lengths);
|
void add_keys_and_lengths(String *key_names, String *used_lengths);
|
||||||
void add_info_string(String *str);
|
void add_info_string(String *str);
|
||||||
bool check_if_keys_used(List<Item> *fields);
|
bool is_keys_used(const MY_BITMAP *fields);
|
||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
void dbug_dump(int indent, bool verbose);
|
void dbug_dump(int indent, bool verbose);
|
||||||
#endif
|
#endif
|
||||||
|
@ -2037,18 +2037,17 @@ close_file:
|
|||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
partition_key_modified
|
partition_key_modified
|
||||||
table TABLE object for which partition fields are set-up
|
table TABLE object for which partition fields are set-up
|
||||||
fields A list of the to be modifed
|
fields Bitmap representing fields to be modified
|
||||||
|
|
||||||
RETURN VALUES
|
RETURN VALUES
|
||||||
TRUE Need special handling of UPDATE
|
TRUE Need special handling of UPDATE
|
||||||
FALSE Normal UPDATE handling is ok
|
FALSE Normal UPDATE handling is ok
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool partition_key_modified(TABLE *table, List<Item> &fields)
|
bool partition_key_modified(TABLE *table, const MY_BITMAP *fields)
|
||||||
{
|
{
|
||||||
List_iterator_fast<Item> f(fields);
|
Field **fld;
|
||||||
partition_info *part_info= table->part_info;
|
partition_info *part_info= table->part_info;
|
||||||
Item_field *item_field;
|
|
||||||
DBUG_ENTER("partition_key_modified");
|
DBUG_ENTER("partition_key_modified");
|
||||||
|
|
||||||
if (!part_info)
|
if (!part_info)
|
||||||
@ -2056,9 +2055,8 @@ bool partition_key_modified(TABLE *table, List<Item> &fields)
|
|||||||
if (table->s->db_type->partition_flags &&
|
if (table->s->db_type->partition_flags &&
|
||||||
(table->s->db_type->partition_flags() & HA_CAN_UPDATE_PARTITION_KEY))
|
(table->s->db_type->partition_flags() & HA_CAN_UPDATE_PARTITION_KEY))
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
f.rewind();
|
for (fld= part_info->full_part_field_array; *fld; fld++)
|
||||||
while ((item_field=(Item_field*) f++))
|
if (bitmap_is_set(fields, (*fld)->field_index))
|
||||||
if (item_field->field->flags & FIELD_IN_PART_FUNC_FLAG)
|
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ bool fix_partition_func(THD *thd, TABLE *table, bool create_table_ind);
|
|||||||
char *generate_partition_syntax(partition_info *part_info,
|
char *generate_partition_syntax(partition_info *part_info,
|
||||||
uint *buf_length, bool use_sql_alloc,
|
uint *buf_length, bool use_sql_alloc,
|
||||||
bool show_partition_options);
|
bool show_partition_options);
|
||||||
bool partition_key_modified(TABLE *table, List<Item> &fields);
|
bool partition_key_modified(TABLE *table, const MY_BITMAP *fields);
|
||||||
void get_partition_set(const TABLE *table, byte *buf, const uint index,
|
void get_partition_set(const TABLE *table, byte *buf, const uint index,
|
||||||
const key_range *key_spec,
|
const key_range *key_spec,
|
||||||
part_id_range *part_spec);
|
part_id_range *part_spec);
|
||||||
|
@ -1582,6 +1582,38 @@ void Table_triggers_list::mark_fields_used(trg_event_type event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Check if field of subject table can be changed in before update trigger.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
is_updated_in_before_update_triggers()
|
||||||
|
field Field object for field to be checked
|
||||||
|
|
||||||
|
NOTE
|
||||||
|
Field passed to this function should be bound to the same
|
||||||
|
TABLE object as Table_triggers_list.
|
||||||
|
|
||||||
|
RETURN VALUE
|
||||||
|
TRUE Field is changed
|
||||||
|
FALSE Otherwise
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool Table_triggers_list::is_updated_in_before_update_triggers(Field *fld)
|
||||||
|
{
|
||||||
|
Item_trigger_field *trg_fld;
|
||||||
|
for (trg_fld= trigger_fields[TRG_EVENT_UPDATE][TRG_ACTION_BEFORE];
|
||||||
|
trg_fld != 0;
|
||||||
|
trg_fld= trg_fld->next_trg_field)
|
||||||
|
{
|
||||||
|
if (trg_fld->get_settable_routine_parameter() &&
|
||||||
|
trg_fld->field_idx != (uint)-1 &&
|
||||||
|
table->field[trg_fld->field_idx]->eq(fld))
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Trigger BUG#14090 compatibility hook
|
Trigger BUG#14090 compatibility hook
|
||||||
|
|
||||||
|
@ -116,11 +116,6 @@ public:
|
|||||||
bodies[TRG_EVENT_DELETE][TRG_ACTION_AFTER]);
|
bodies[TRG_EVENT_DELETE][TRG_ACTION_AFTER]);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool has_before_update_triggers()
|
|
||||||
{
|
|
||||||
return test(bodies[TRG_EVENT_UPDATE][TRG_ACTION_BEFORE]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_table(TABLE *new_table);
|
void set_table(TABLE *new_table);
|
||||||
|
|
||||||
void mark_fields_used(trg_event_type event);
|
void mark_fields_used(trg_event_type event);
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
#include "sp_head.h"
|
#include "sp_head.h"
|
||||||
#include "sql_trigger.h"
|
#include "sql_trigger.h"
|
||||||
|
|
||||||
static bool safe_update_on_fly(JOIN_TAB *join_tab, List<Item> *fields);
|
static bool safe_update_on_fly(JOIN_TAB *join_tab);
|
||||||
|
|
||||||
/* Return 0 if row hasn't changed */
|
/* Return 0 if row hasn't changed */
|
||||||
|
|
||||||
@ -271,13 +271,16 @@ int mysql_update(THD *thd,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
init_ftfuncs(thd, select_lex, 1);
|
init_ftfuncs(thd, select_lex, 1);
|
||||||
|
|
||||||
|
table->mark_columns_needed_for_update();
|
||||||
|
|
||||||
/* Check if we are modifying a key that we are used to search with */
|
/* Check if we are modifying a key that we are used to search with */
|
||||||
|
|
||||||
if (select && select->quick)
|
if (select && select->quick)
|
||||||
{
|
{
|
||||||
used_index= select->quick->index;
|
used_index= select->quick->index;
|
||||||
used_key_is_modified= (!select->quick->unique_key_range() &&
|
used_key_is_modified= (!select->quick->unique_key_range() &&
|
||||||
select->quick->check_if_keys_used(&fields));
|
select->quick->is_keys_used(table->write_set));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -285,12 +288,13 @@ int mysql_update(THD *thd,
|
|||||||
if (used_index == MAX_KEY) // no index for sort order
|
if (used_index == MAX_KEY) // no index for sort order
|
||||||
used_index= table->file->key_used_on_scan;
|
used_index= table->file->key_used_on_scan;
|
||||||
if (used_index != MAX_KEY)
|
if (used_index != MAX_KEY)
|
||||||
used_key_is_modified= check_if_key_used(table, used_index, fields);
|
used_key_is_modified= is_key_used(table, used_index, table->write_set);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||||
if (used_key_is_modified || order ||
|
if (used_key_is_modified || order ||
|
||||||
partition_key_modified(table, fields))
|
partition_key_modified(table, table->write_set))
|
||||||
#else
|
#else
|
||||||
if (used_key_is_modified || order)
|
if (used_key_is_modified || order)
|
||||||
#endif
|
#endif
|
||||||
@ -449,8 +453,6 @@ int mysql_update(THD *thd,
|
|||||||
MODE_STRICT_ALL_TABLES)));
|
MODE_STRICT_ALL_TABLES)));
|
||||||
will_batch= !table->file->start_bulk_update();
|
will_batch= !table->file->start_bulk_update();
|
||||||
|
|
||||||
table->mark_columns_needed_for_update();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We can use compare_record() to optimize away updates if
|
We can use compare_record() to optimize away updates if
|
||||||
the table handler is returning all columns OR if
|
the table handler is returning all columns OR if
|
||||||
@ -1217,7 +1219,7 @@ multi_update::initialize_tables(JOIN *join)
|
|||||||
table->mark_columns_needed_for_update();
|
table->mark_columns_needed_for_update();
|
||||||
if (table == main_table) // First table in join
|
if (table == main_table) // First table in join
|
||||||
{
|
{
|
||||||
if (safe_update_on_fly(join->join_tab, &temp_fields))
|
if (safe_update_on_fly(join->join_tab))
|
||||||
{
|
{
|
||||||
table_to_update= main_table; // Update table on the fly
|
table_to_update= main_table; // Update table on the fly
|
||||||
continue;
|
continue;
|
||||||
@ -1275,7 +1277,6 @@ multi_update::initialize_tables(JOIN *join)
|
|||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
safe_update_on_fly
|
safe_update_on_fly
|
||||||
join_tab How table is used in join
|
join_tab How table is used in join
|
||||||
fields Fields that are updated
|
|
||||||
|
|
||||||
NOTES
|
NOTES
|
||||||
We can update the first table in join on the fly if we know that
|
We can update the first table in join on the fly if we know that
|
||||||
@ -1288,9 +1289,8 @@ multi_update::initialize_tables(JOIN *join)
|
|||||||
- We are doing a range scan and we don't update the scan key or
|
- We are doing a range scan and we don't update the scan key or
|
||||||
the primary key for a clustered table handler.
|
the primary key for a clustered table handler.
|
||||||
|
|
||||||
When checking for above cases we also should take into account that
|
This function gets information about fields to be updated from
|
||||||
BEFORE UPDATE trigger potentially may change value of any field in row
|
the TABLE::write_set bitmap.
|
||||||
being updated.
|
|
||||||
|
|
||||||
WARNING
|
WARNING
|
||||||
This code is a bit dependent of how make_join_readinfo() works.
|
This code is a bit dependent of how make_join_readinfo() works.
|
||||||
@ -1300,7 +1300,7 @@ multi_update::initialize_tables(JOIN *join)
|
|||||||
1 Safe to update
|
1 Safe to update
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static bool safe_update_on_fly(JOIN_TAB *join_tab, List<Item> *fields)
|
static bool safe_update_on_fly(JOIN_TAB *join_tab)
|
||||||
{
|
{
|
||||||
TABLE *table= join_tab->table;
|
TABLE *table= join_tab->table;
|
||||||
switch (join_tab->type) {
|
switch (join_tab->type) {
|
||||||
@ -1310,21 +1310,15 @@ static bool safe_update_on_fly(JOIN_TAB *join_tab, List<Item> *fields)
|
|||||||
return TRUE; // At most one matching row
|
return TRUE; // At most one matching row
|
||||||
case JT_REF:
|
case JT_REF:
|
||||||
case JT_REF_OR_NULL:
|
case JT_REF_OR_NULL:
|
||||||
return !check_if_key_used(table, join_tab->ref.key, *fields) &&
|
return !is_key_used(table, join_tab->ref.key, table->write_set);
|
||||||
!(table->triggers &&
|
|
||||||
table->triggers->has_before_update_triggers());
|
|
||||||
case JT_ALL:
|
case JT_ALL:
|
||||||
/* If range search on index */
|
/* If range search on index */
|
||||||
if (join_tab->quick)
|
if (join_tab->quick)
|
||||||
return !join_tab->quick->check_if_keys_used(fields) &&
|
return !join_tab->quick->is_keys_used(table->write_set);
|
||||||
!(table->triggers &&
|
|
||||||
table->triggers->has_before_update_triggers());
|
|
||||||
/* If scanning in clustered key */
|
/* If scanning in clustered key */
|
||||||
if ((table->file->ha_table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX) &&
|
if ((table->file->ha_table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX) &&
|
||||||
table->s->primary_key < MAX_KEY)
|
table->s->primary_key < MAX_KEY)
|
||||||
return !check_if_key_used(table, table->s->primary_key, *fields) &&
|
return !is_key_used(table, table->s->primary_key, table->write_set);
|
||||||
!(table->triggers &&
|
|
||||||
table->triggers->has_before_update_triggers());
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
default:
|
default:
|
||||||
break; // Avoid compler warning
|
break; // Avoid compler warning
|
||||||
|
Loading…
x
Reference in New Issue
Block a user