Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mariadb
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
93fed182
Commit
93fed182
authored
Sep 30, 2006
by
dlenev@mockturtle.local
Browse files
Options
Browse Files
Download
Plain Diff
Merge bk-internal.mysql.com:/home/bk/mysql-5.1-runtime
into mockturtle.local:/home/dlenev/src/mysql-5.1-bg20670
parents
8b63a55b
ae117f23
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
119 additions
and
72 deletions
+119
-72
mysql-test/r/trigger.result
mysql-test/r/trigger.result
+12
-0
mysql-test/t/trigger.test
mysql-test/t/trigger.test
+19
-0
sql/key.cc
sql/key.cc
+21
-23
sql/mysql_priv.h
sql/mysql_priv.h
+1
-1
sql/opt_range.cc
sql/opt_range.cc
+8
-8
sql/opt_range.h
sql/opt_range.h
+5
-6
sql/sql_partition.cc
sql/sql_partition.cc
+5
-7
sql/sql_partition.h
sql/sql_partition.h
+1
-1
sql/sql_trigger.cc
sql/sql_trigger.cc
+32
-0
sql/sql_trigger.h
sql/sql_trigger.h
+0
-5
sql/sql_update.cc
sql/sql_update.cc
+15
-21
No files found.
mysql-test/r/trigger.result
View file @
93fed182
...
...
@@ -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)
DROP TABLE t1;
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
mysql-test/t/trigger.test
View file @
93fed182
...
...
@@ -1421,4 +1421,23 @@ DROP TABLE t1;
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
sql/key.cc
View file @
93fed182
...
...
@@ -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
that is automaticly updated (like a timestamp)
Check if key uses field that is marked in passed field bitmap.
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
);
KEY_PART_INFO
*
key_part
,
*
key_part_end
;
for
(
key_part
=
table
->
key_info
[
idx
].
key_part
,
key_part_end
=
key_part
+
table
->
key_info
[
idx
].
key_parts
;
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
))
bitmap_clear_all
(
&
table
->
tmp_set
);
table
->
mark_columns_used_by_index_no_reset
(
idx
,
&
table
->
tmp_set
);
if
(
bitmap_is_overlapping
(
&
table
->
tmp_set
,
fields
))
return
1
;
}
}
/*
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
&&
(
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
;
}
...
...
sql/mysql_priv.h
View file @
93fed182
...
...
@@ -1417,7 +1417,7 @@ void key_restore(byte *to_record, byte *from_key, KEY *key_info,
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
);
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_rec_cmp
(
void
*
key_info
,
byte
*
a
,
byte
*
b
);
...
...
sql/opt_range.cc
View file @
93fed182
...
...
@@ -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
;
List_iterator_fast
<
QUICK_RANGE_SELECT
>
it
(
quick_selects
);
while
((
quick
=
it
++
))
{
if
(
check_if_key_used
(
head
,
quick
->
index
,
*
fields
))
if
(
is_key_used
(
head
,
quick
->
index
,
fields
))
return
1
;
}
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
;
List_iterator_fast
<
QUICK_RANGE_SELECT
>
it
(
quick_selects
);
while
((
quick
=
it
++
))
{
if
(
check_if_key_used
(
head
,
quick
->
index
,
*
fields
))
if
(
is_key_used
(
head
,
quick
->
index
,
fields
))
return
1
;
}
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
;
List_iterator_fast
<
QUICK_SELECT_I
>
it
(
quick_selects
);
while
((
quick
=
it
++
))
{
if
(
quick
->
check_if
_keys_used
(
fields
))
if
(
quick
->
is
_keys_used
(
fields
))
return
1
;
}
return
0
;
...
...
sql/opt_range.h
View file @
93fed182
...
...
@@ -224,10 +224,9 @@ public:
virtual
void
add_info_string
(
String
*
str
)
{};
/*
Return 1 if any index used by this quick select
a) uses field that is listed in passed field list or
b) is automatically updated (like a timestamp)
uses field which is marked in passed bitmap.
*/
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
...
...
@@ -425,7 +424,7 @@ public:
int
get_type
()
{
return
QS_TYPE_INDEX_MERGE
;
}
void
add_keys_and_lengths
(
String
*
key_names
,
String
*
used_lengths
);
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
void
dbug_dump
(
int
indent
,
bool
verbose
);
#endif
...
...
@@ -484,7 +483,7 @@ public:
int
get_type
()
{
return
QS_TYPE_ROR_INTERSECT
;
}
void
add_keys_and_lengths
(
String
*
key_names
,
String
*
used_lengths
);
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
void
dbug_dump
(
int
indent
,
bool
verbose
);
#endif
...
...
@@ -538,7 +537,7 @@ public:
int
get_type
()
{
return
QS_TYPE_ROR_UNION
;
}
void
add_keys_and_lengths
(
String
*
key_names
,
String
*
used_lengths
);
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
void
dbug_dump
(
int
indent
,
bool
verbose
);
#endif
...
...
sql/sql_partition.cc
View file @
93fed182
...
...
@@ -2037,18 +2037,17 @@ close_file:
SYNOPSIS
partition_key_modified
table TABLE object for which partition fields are set-up
fields
A list of the to be modif
ed
fields
Bitmap representing fields to be modifi
ed
RETURN VALUES
TRUE Need special handling of UPDATE
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
;
Item_field
*
item_field
;
DBUG_ENTER
(
"partition_key_modified"
);
if
(
!
part_info
)
...
...
@@ -2056,9 +2055,8 @@ bool partition_key_modified(TABLE *table, List<Item> &fields)
if
(
table
->
s
->
db_type
->
partition_flags
&&
(
table
->
s
->
db_type
->
partition_flags
()
&
HA_CAN_UPDATE_PARTITION_KEY
))
DBUG_RETURN
(
FALSE
);
f
.
rewind
();
while
((
item_field
=
(
Item_field
*
)
f
++
))
if
(
item_field
->
field
->
flags
&
FIELD_IN_PART_FUNC_FLAG
)
for
(
fld
=
part_info
->
full_part_field_array
;
*
fld
;
fld
++
)
if
(
bitmap_is_set
(
fields
,
(
*
fld
)
->
field_index
))
DBUG_RETURN
(
TRUE
);
DBUG_RETURN
(
FALSE
);
}
...
...
sql/sql_partition.h
View file @
93fed182
...
...
@@ -70,7 +70,7 @@ bool fix_partition_func(THD *thd, TABLE *table, bool create_table_ind);
char
*
generate_partition_syntax
(
partition_info
*
part_info
,
uint
*
buf_length
,
bool
use_sql_alloc
,
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
,
const
key_range
*
key_spec
,
part_id_range
*
part_spec
);
...
...
sql/sql_trigger.cc
View file @
93fed182
...
...
@@ -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
...
...
sql/sql_trigger.h
View file @
93fed182
...
...
@@ -116,11 +116,6 @@ public:
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
mark_fields_used
(
trg_event_type
event
);
...
...
sql/sql_update.cc
View file @
93fed182
...
...
@@ -25,7 +25,7 @@
#include "sp_head.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 */
...
...
@@ -271,13 +271,16 @@ int mysql_update(THD *thd,
}
}
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 */
if
(
select
&&
select
->
quick
)
{
used_index
=
select
->
quick
->
index
;
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
{
...
...
@@ -285,12 +288,13 @@ int mysql_update(THD *thd,
if
(
used_index
==
MAX_KEY
)
// no index for sort order
used_index
=
table
->
file
->
key_used_on_scan
;
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
if
(
used_key_is_modified
||
order
||
partition_key_modified
(
table
,
fields
))
partition_key_modified
(
table
,
table
->
write_set
))
#else
if
(
used_key_is_modified
||
order
)
#endif
...
...
@@ -449,8 +453,6 @@ int mysql_update(THD *thd,
MODE_STRICT_ALL_TABLES
)));
will_batch
=
!
table
->
file
->
start_bulk_update
();
table
->
mark_columns_needed_for_update
();
/*
We can use compare_record() to optimize away updates 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
();
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
continue
;
...
...
@@ -1275,7 +1277,6 @@ multi_update::initialize_tables(JOIN *join)
SYNOPSIS
safe_update_on_fly
join_tab How table is used in join
fields Fields that are updated
NOTES
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
the primary key for a clustered table handler.
When checking for above cases we also should take into account that
BEFORE UPDATE trigger potentially may change value of any field in row
being updated.
This function gets information about fields to be updated from
the TABLE::write_set bitmap.
WARNING
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
*/
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
;
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
case
JT_REF
:
case
JT_REF_OR_NULL
:
return
!
check_if_key_used
(
table
,
join_tab
->
ref
.
key
,
*
fields
)
&&
!
(
table
->
triggers
&&
table
->
triggers
->
has_before_update_triggers
());
return
!
is_key_used
(
table
,
join_tab
->
ref
.
key
,
table
->
write_set
);
case
JT_ALL
:
/* If range search on index */
if
(
join_tab
->
quick
)
return
!
join_tab
->
quick
->
check_if_keys_used
(
fields
)
&&
!
(
table
->
triggers
&&
table
->
triggers
->
has_before_update_triggers
());
return
!
join_tab
->
quick
->
is_keys_used
(
table
->
write_set
);
/* If scanning in clustered key */
if
((
table
->
file
->
ha_table_flags
()
&
HA_PRIMARY_KEY_IN_READ_INDEX
)
&&
table
->
s
->
primary_key
<
MAX_KEY
)
return
!
check_if_key_used
(
table
,
table
->
s
->
primary_key
,
*
fields
)
&&
!
(
table
->
triggers
&&
table
->
triggers
->
has_before_update_triggers
());
return
!
is_key_used
(
table
,
table
->
s
->
primary_key
,
table
->
write_set
);
return
TRUE
;
default:
break
;
// Avoid compler warning
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment