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
9f9d7185
Commit
9f9d7185
authored
May 30, 2007
by
gshchepa/uchum@gleb.loc
Browse files
Options
Browse Files
Download
Plain Diff
Merge gshchepa@bk-internal.mysql.com:/home/bk/mysql-5.0-opt
into gleb.loc:/home/uchum/work/bk/mysql-5.0-opt
parents
22c1bfbb
0362400f
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
150 additions
and
29 deletions
+150
-29
mysql-test/r/view.result
mysql-test/r/view.result
+17
-0
mysql-test/t/view.test
mysql-test/t/view.test
+16
-0
sql/sql_class.h
sql/sql_class.h
+5
-0
sql/sql_update.cc
sql/sql_update.cc
+112
-29
No files found.
mysql-test/r/view.result
View file @
9f9d7185
...
@@ -3367,6 +3367,23 @@ SHOW CREATE VIEW v1;
...
@@ -3367,6 +3367,23 @@ SHOW CREATE VIEW v1;
View Create View
View Create View
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(1.23456789 as decimal(8,0)) AS `col`
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(1.23456789 as decimal(8,0)) AS `col`
DROP VIEW v1;
DROP VIEW v1;
CREATE TABLE t1 (a INT);
CREATE TABLE t2 (b INT, c INT DEFAULT 0);
INSERT INTO t1 (a) VALUES (1), (2);
INSERT INTO t2 (b) VALUES (1), (2);
CREATE VIEW v1 AS SELECT t2.b,t2.c FROM t1, t2
WHERE t1.a=t2.b AND t2.b < 3 WITH CHECK OPTION;
SELECT * FROM v1;
b c
1 0
2 0
UPDATE v1 SET c=1 WHERE b=1;
SELECT * FROM v1;
b c
1 1
2 0
DROP VIEW v1;
DROP TABLE t1,t2;
CREATE TABLE t1 (id int);
CREATE TABLE t1 (id int);
CREATE TABLE t2 (id int, c int DEFAULT 0);
CREATE TABLE t2 (id int, c int DEFAULT 0);
INSERT INTO t1 (id) VALUES (1);
INSERT INTO t1 (id) VALUES (1);
...
...
mysql-test/t/view.test
View file @
9f9d7185
...
@@ -3233,6 +3233,22 @@ CREATE VIEW v1 AS SELECT CAST(1.23456789 AS DECIMAL(8,0)) AS col;
...
@@ -3233,6 +3233,22 @@ CREATE VIEW v1 AS SELECT CAST(1.23456789 AS DECIMAL(8,0)) AS col;
SHOW
CREATE
VIEW
v1
;
SHOW
CREATE
VIEW
v1
;
DROP
VIEW
v1
;
DROP
VIEW
v1
;
#
# Bug #28716: CHECK OPTION expression is evaluated over expired record buffers
# when VIEW is updated via temporary tables
#
CREATE
TABLE
t1
(
a
INT
);
CREATE
TABLE
t2
(
b
INT
,
c
INT
DEFAULT
0
);
INSERT
INTO
t1
(
a
)
VALUES
(
1
),
(
2
);
INSERT
INTO
t2
(
b
)
VALUES
(
1
),
(
2
);
CREATE
VIEW
v1
AS
SELECT
t2
.
b
,
t2
.
c
FROM
t1
,
t2
WHERE
t1
.
a
=
t2
.
b
AND
t2
.
b
<
3
WITH
CHECK
OPTION
;
SELECT
*
FROM
v1
;
UPDATE
v1
SET
c
=
1
WHERE
b
=
1
;
SELECT
*
FROM
v1
;
DROP
VIEW
v1
;
DROP
TABLE
t1
,
t2
;
#
#
# Bug #28561: update on multi-table view with CHECK OPTION and
# Bug #28561: update on multi-table view with CHECK OPTION and
# a subquery in WHERE condition
# a subquery in WHERE condition
...
...
sql/sql_class.h
View file @
9f9d7185
...
@@ -2283,6 +2283,11 @@ class multi_update :public select_result_interceptor
...
@@ -2283,6 +2283,11 @@ class multi_update :public select_result_interceptor
List
<
Item
>
*
fields
,
*
values
;
List
<
Item
>
*
fields
,
*
values
;
List
<
Item
>
**
fields_for_table
,
**
values_for_table
;
List
<
Item
>
**
fields_for_table
,
**
values_for_table
;
uint
table_count
;
uint
table_count
;
/*
List of tables referenced in the CHECK OPTION condition of
the updated view excluding the updated table.
*/
List
<
TABLE
>
unupdated_check_opt_tables
;
Copy_field
*
copy_field
;
Copy_field
*
copy_field
;
enum
enum_duplicates
handle_duplicates
;
enum
enum_duplicates
handle_duplicates
;
bool
do_update
,
trans_safe
;
bool
do_update
,
trans_safe
;
...
...
sql/sql_update.cc
View file @
9f9d7185
...
@@ -970,6 +970,7 @@ int multi_update::prepare(List<Item> ¬_used_values,
...
@@ -970,6 +970,7 @@ int multi_update::prepare(List<Item> ¬_used_values,
List_iterator_fast
<
Item
>
field_it
(
*
fields
);
List_iterator_fast
<
Item
>
field_it
(
*
fields
);
List_iterator_fast
<
Item
>
value_it
(
*
values
);
List_iterator_fast
<
Item
>
value_it
(
*
values
);
uint
i
,
max_fields
;
uint
i
,
max_fields
;
uint
leaf_table_count
=
0
;
DBUG_ENTER
(
"multi_update::prepare"
);
DBUG_ENTER
(
"multi_update::prepare"
);
thd
->
count_cuted_fields
=
CHECK_FIELD_WARN
;
thd
->
count_cuted_fields
=
CHECK_FIELD_WARN
;
...
@@ -1003,6 +1004,7 @@ int multi_update::prepare(List<Item> ¬_used_values,
...
@@ -1003,6 +1004,7 @@ int multi_update::prepare(List<Item> ¬_used_values,
{
{
/* TODO: add support of view of join support */
/* TODO: add support of view of join support */
TABLE
*
table
=
table_ref
->
table
;
TABLE
*
table
=
table_ref
->
table
;
leaf_table_count
++
;
if
(
tables_to_update
&
table
->
map
)
if
(
tables_to_update
&
table
->
map
)
{
{
TABLE_LIST
*
tl
=
(
TABLE_LIST
*
)
thd
->
memdup
((
char
*
)
table_ref
,
TABLE_LIST
*
tl
=
(
TABLE_LIST
*
)
thd
->
memdup
((
char
*
)
table_ref
,
...
@@ -1067,7 +1069,7 @@ int multi_update::prepare(List<Item> ¬_used_values,
...
@@ -1067,7 +1069,7 @@ int multi_update::prepare(List<Item> ¬_used_values,
/* Allocate copy fields */
/* Allocate copy fields */
max_fields
=
0
;
max_fields
=
0
;
for
(
i
=
0
;
i
<
table_count
;
i
++
)
for
(
i
=
0
;
i
<
table_count
;
i
++
)
set_if_bigger
(
max_fields
,
fields_for_table
[
i
]
->
elements
);
set_if_bigger
(
max_fields
,
fields_for_table
[
i
]
->
elements
+
leaf_table_count
);
copy_field
=
new
Copy_field
[
max_fields
];
copy_field
=
new
Copy_field
[
max_fields
];
DBUG_RETURN
(
thd
->
is_fatal_error
!=
0
);
DBUG_RETURN
(
thd
->
is_fatal_error
!=
0
);
}
}
...
@@ -1160,13 +1162,22 @@ multi_update::initialize_tables(JOIN *join)
...
@@ -1160,13 +1162,22 @@ multi_update::initialize_tables(JOIN *join)
trans_safe
=
transactional_tables
=
main_table
->
file
->
has_transactions
();
trans_safe
=
transactional_tables
=
main_table
->
file
->
has_transactions
();
table_to_update
=
0
;
table_to_update
=
0
;
/* Any update has at least one pair (field, value) */
DBUG_ASSERT
(
fields
->
elements
);
/*
Only one table may be modified by UPDATE of an updatable view.
For an updatable view first_table_for_update indicates this
table.
For a regular multi-update it refers to some updated table.
*/
TABLE
*
first_table_for_update
=
((
Item_field
*
)
fields
->
head
())
->
field
->
table
;
/* Create a temporary table for keys to all tables, except main table */
/* Create a temporary table for keys to all tables, except main table */
for
(
table_ref
=
update_tables
;
table_ref
;
table_ref
=
table_ref
->
next_local
)
for
(
table_ref
=
update_tables
;
table_ref
;
table_ref
=
table_ref
->
next_local
)
{
{
TABLE
*
table
=
table_ref
->
table
;
TABLE
*
table
=
table_ref
->
table
;
uint
cnt
=
table_ref
->
shared
;
uint
cnt
=
table_ref
->
shared
;
Item_field
*
ifield
;
List
<
Item
>
temp_fields
;
List
<
Item
>
temp_fields
=
*
fields_for_table
[
cnt
];
ORDER
group
;
ORDER
group
;
if
(
ignore
)
if
(
ignore
)
...
@@ -1174,34 +1185,63 @@ multi_update::initialize_tables(JOIN *join)
...
@@ -1174,34 +1185,63 @@ multi_update::initialize_tables(JOIN *join)
if
(
table
==
main_table
)
// First table in join
if
(
table
==
main_table
)
// First table in join
{
{
if
(
safe_update_on_fly
(
thd
,
join
->
join_tab
,
table_ref
,
all_tables
,
if
(
safe_update_on_fly
(
thd
,
join
->
join_tab
,
table_ref
,
all_tables
,
&
temp_fields
))
fields_for_table
[
cnt
]
))
{
{
table_to_update
=
main_table
;
// Update table on the fly
table_to_update
=
main_table
;
// Update table on the fly
continue
;
continue
;
}
}
}
}
if
(
table
==
first_table_for_update
&&
table_ref
->
check_option
)
{
table_map
unupdated_tables
=
table_ref
->
check_option
->
used_tables
()
&
~
first_table_for_update
->
map
;
for
(
TABLE_LIST
*
tbl_ref
=
leaves
;
unupdated_tables
&&
tbl_ref
;
tbl_ref
=
tbl_ref
->
next_leaf
)
{
if
(
unupdated_tables
&
tbl_ref
->
table
->
map
)
unupdated_tables
&=
~
tbl_ref
->
table
->
map
;
else
continue
;
if
(
unupdated_check_opt_tables
.
push_back
(
tbl_ref
->
table
))
DBUG_RETURN
(
1
);
}
}
TMP_TABLE_PARAM
*
tmp_param
=
tmp_table_param
+
cnt
;
TMP_TABLE_PARAM
*
tmp_param
=
tmp_table_param
+
cnt
;
/*
/*
Create a temporary table to store all fields that are changed for this
Create a temporary table to store all fields that are changed for this
table. The first field in the temporary table is a pointer to the
table. The first field in the temporary table is a pointer to the
original row so that we can find and update it
original row so that we can find and update it. For the updatable
VIEW a few following fields are rowids of tables used in the CHECK
OPTION condition.
*/
*/
/* ok to be on stack as this is not referenced outside of this func */
List_iterator_fast
<
TABLE
>
tbl_it
(
unupdated_check_opt_tables
);
Field_string
offset
(
table
->
file
->
ref_length
,
0
,
"offset"
,
TABLE
*
tbl
=
table
;
table
,
&
my_charset_bin
);
do
{
Field_string
*
field
=
new
Field_string
(
tbl
->
file
->
ref_length
,
0
,
tbl
->
alias
,
tbl
,
&
my_charset_bin
);
if
(
!
field
)
DBUG_RETURN
(
1
);
/*
/*
The field will be converted to varstring when creating tmp table if
The field will be converted to varstring when creating tmp table if
table to be updated was created by mysql 4.1. Deny this.
table to be updated was created by mysql 4.1. Deny this.
*/
*/
offset
.
can_alter_field_type
=
0
;
field
->
can_alter_field_type
=
0
;
if
(
!
(
ifield
=
new
Item_field
(((
Field
*
)
&
offset
))))
Item_field
*
ifield
=
new
Item_field
((
Field
*
)
field
);
if
(
!
ifield
)
DBUG_RETURN
(
1
);
DBUG_RETURN
(
1
);
ifield
->
maybe_null
=
0
;
ifield
->
maybe_null
=
0
;
if
(
temp_fields
.
push_front
(
ifield
))
if
(
temp_fields
.
push_back
(
ifield
))
DBUG_RETURN
(
1
);
DBUG_RETURN
(
1
);
}
while
((
tbl
=
tbl_it
++
));
temp_fields
.
concat
(
fields_for_table
[
cnt
]);
/* Make an unique key over the first field to avoid duplicated updates */
/* Make an unique key over the first field to avoid duplicated updates */
bzero
((
char
*
)
&
group
,
sizeof
(
group
));
bzero
((
char
*
)
&
group
,
sizeof
(
group
));
...
@@ -1350,10 +1390,26 @@ bool multi_update::send_data(List<Item> ¬_used_values)
...
@@ -1350,10 +1390,26 @@ bool multi_update::send_data(List<Item> ¬_used_values)
{
{
int
error
;
int
error
;
TABLE
*
tmp_table
=
tmp_tables
[
offset
];
TABLE
*
tmp_table
=
tmp_tables
[
offset
];
fill_record
(
thd
,
tmp_table
->
field
+
1
,
*
values_for_table
[
offset
],
1
);
/* Store regular updated fields in the row. */
/* Store pointer to row */
fill_record
(
thd
,
memcpy
((
char
*
)
tmp_table
->
field
[
0
]
->
ptr
,
tmp_table
->
field
+
1
+
unupdated_check_opt_tables
.
elements
,
(
char
*
)
table
->
file
->
ref
,
table
->
file
->
ref_length
);
*
values_for_table
[
offset
],
1
);
/*
For updatable VIEW store rowid of the updated table and
rowids of tables used in the CHECK OPTION condition.
*/
uint
field_num
=
0
;
List_iterator_fast
<
TABLE
>
tbl_it
(
unupdated_check_opt_tables
);
TABLE
*
tbl
=
table
;
do
{
if
(
tbl
!=
table
)
tbl
->
file
->
position
(
tbl
->
record
[
0
]);
memcpy
((
char
*
)
tmp_table
->
field
[
field_num
]
->
ptr
,
(
char
*
)
tbl
->
file
->
ref
,
tbl
->
file
->
ref_length
);
field_num
++
;
}
while
((
tbl
=
tbl_it
++
));
/* Write row, ignoring duplicated updates to a row */
/* Write row, ignoring duplicated updates to a row */
error
=
tmp_table
->
file
->
write_row
(
tmp_table
->
record
[
0
]);
error
=
tmp_table
->
file
->
write_row
(
tmp_table
->
record
[
0
]);
if
(
error
!=
HA_ERR_FOUND_DUPP_KEY
&&
error
!=
HA_ERR_FOUND_DUPP_UNIQUE
)
if
(
error
!=
HA_ERR_FOUND_DUPP_KEY
&&
error
!=
HA_ERR_FOUND_DUPP_UNIQUE
)
...
@@ -1403,9 +1459,10 @@ void multi_update::send_error(uint errcode,const char *err)
...
@@ -1403,9 +1459,10 @@ void multi_update::send_error(uint errcode,const char *err)
int
multi_update
::
do_updates
(
bool
from_send_error
)
int
multi_update
::
do_updates
(
bool
from_send_error
)
{
{
TABLE_LIST
*
cur_table
;
TABLE_LIST
*
cur_table
;
int
local_error
;
int
local_error
=
0
;
ha_rows
org_updated
;
ha_rows
org_updated
;
TABLE
*
table
,
*
tmp_table
;
TABLE
*
table
,
*
tmp_table
;
List_iterator_fast
<
TABLE
>
check_opt_it
(
unupdated_check_opt_tables
);
DBUG_ENTER
(
"do_updates"
);
DBUG_ENTER
(
"do_updates"
);
do_update
=
0
;
// Don't retry this function
do_update
=
0
;
// Don't retry this function
...
@@ -1413,8 +1470,8 @@ int multi_update::do_updates(bool from_send_error)
...
@@ -1413,8 +1470,8 @@ int multi_update::do_updates(bool from_send_error)
DBUG_RETURN
(
0
);
DBUG_RETURN
(
0
);
for
(
cur_table
=
update_tables
;
cur_table
;
cur_table
=
cur_table
->
next_local
)
for
(
cur_table
=
update_tables
;
cur_table
;
cur_table
=
cur_table
->
next_local
)
{
{
byte
*
ref_pos
;
bool
can_compare_record
;
bool
can_compare_record
;
uint
offset
=
cur_table
->
shared
;
table
=
cur_table
->
table
;
table
=
cur_table
->
table
;
if
(
table
==
table_to_update
)
if
(
table
==
table_to_update
)
...
@@ -1425,11 +1482,20 @@ int multi_update::do_updates(bool from_send_error)
...
@@ -1425,11 +1482,20 @@ int multi_update::do_updates(bool from_send_error)
(
void
)
table
->
file
->
ha_rnd_init
(
0
);
(
void
)
table
->
file
->
ha_rnd_init
(
0
);
table
->
file
->
extra
(
HA_EXTRA_NO_CACHE
);
table
->
file
->
extra
(
HA_EXTRA_NO_CACHE
);
check_opt_it
.
rewind
();
while
(
TABLE
*
tbl
=
check_opt_it
++
)
{
if
(
tbl
->
file
->
ha_rnd_init
(
1
))
goto
err
;
tbl
->
file
->
extra
(
HA_EXTRA_CACHE
);
}
/*
/*
Setup copy functions to copy fields from temporary table
Setup copy functions to copy fields from temporary table
*/
*/
List_iterator_fast
<
Item
>
field_it
(
*
fields_for_table
[
cur_table
->
shared
]);
List_iterator_fast
<
Item
>
field_it
(
*
fields_for_table
[
offset
]);
Field
**
field
=
tmp_table
->
field
+
1
;
// Skip row pointer
Field
**
field
=
tmp_table
->
field
+
1
+
unupdated_check_opt_tables
.
elements
;
// Skip row pointers
Copy_field
*
copy_field_ptr
=
copy_field
,
*
copy_field_end
;
Copy_field
*
copy_field_ptr
=
copy_field
,
*
copy_field_end
;
for
(
;
*
field
;
field
++
)
for
(
;
*
field
;
field
++
)
{
{
...
@@ -1444,7 +1510,6 @@ int multi_update::do_updates(bool from_send_error)
...
@@ -1444,7 +1510,6 @@ int multi_update::do_updates(bool from_send_error)
can_compare_record
=
!
(
table
->
file
->
table_flags
()
&
can_compare_record
=
!
(
table
->
file
->
table_flags
()
&
HA_PARTIAL_COLUMN_READ
);
HA_PARTIAL_COLUMN_READ
);
ref_pos
=
(
byte
*
)
tmp_table
->
field
[
0
]
->
ptr
;
for
(;;)
for
(;;)
{
{
if
(
thd
->
killed
&&
trans_safe
)
if
(
thd
->
killed
&&
trans_safe
)
...
@@ -1457,8 +1522,19 @@ int multi_update::do_updates(bool from_send_error)
...
@@ -1457,8 +1522,19 @@ int multi_update::do_updates(bool from_send_error)
continue
;
// May happen on dup key
continue
;
// May happen on dup key
goto
err
;
goto
err
;
}
}
if
((
local_error
=
table
->
file
->
rnd_pos
(
table
->
record
[
0
],
ref_pos
)))
/* call rnd_pos() using rowids from temporary table */
check_opt_it
.
rewind
();
TABLE
*
tbl
=
table
;
uint
field_num
=
0
;
do
{
if
((
local_error
=
tbl
->
file
->
rnd_pos
(
tbl
->
record
[
0
],
tmp_table
->
field
[
field_num
]
->
ptr
)))
goto
err
;
goto
err
;
field_num
++
;
}
while
((
tbl
=
check_opt_it
++
));
table
->
status
|=
STATUS_UPDATED
;
table
->
status
|=
STATUS_UPDATED
;
store_record
(
table
,
record
[
1
]);
store_record
(
table
,
record
[
1
]);
...
@@ -1508,6 +1584,10 @@ int multi_update::do_updates(bool from_send_error)
...
@@ -1508,6 +1584,10 @@ int multi_update::do_updates(bool from_send_error)
}
}
(
void
)
table
->
file
->
ha_rnd_end
();
(
void
)
table
->
file
->
ha_rnd_end
();
(
void
)
tmp_table
->
file
->
ha_rnd_end
();
(
void
)
tmp_table
->
file
->
ha_rnd_end
();
check_opt_it
.
rewind
();
while
(
TABLE
*
tbl
=
check_opt_it
++
)
tbl
->
file
->
ha_rnd_end
();
}
}
DBUG_RETURN
(
0
);
DBUG_RETURN
(
0
);
...
@@ -1521,6 +1601,9 @@ err:
...
@@ -1521,6 +1601,9 @@ err:
err2:
err2:
(
void
)
table
->
file
->
ha_rnd_end
();
(
void
)
table
->
file
->
ha_rnd_end
();
(
void
)
tmp_table
->
file
->
ha_rnd_end
();
(
void
)
tmp_table
->
file
->
ha_rnd_end
();
check_opt_it
.
rewind
();
while
(
TABLE
*
tbl
=
check_opt_it
++
)
tbl
->
file
->
ha_rnd_end
();
if
(
updated
!=
org_updated
)
if
(
updated
!=
org_updated
)
{
{
...
...
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