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
7b4ed800
Commit
7b4ed800
authored
May 31, 2007
by
gshchepa/uchum@gleb.loc
Browse files
Options
Browse Files
Download
Plain Diff
Merge gshchepa@bk-internal.mysql.com:/home/bk/mysql-5.1-opt
into gleb.loc:/home/uchum/work/bk/mysql-5.1-opt
parents
4fb062de
89a4d89c
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
151 additions
and
59 deletions
+151
-59
mysql-test/r/view.result
mysql-test/r/view.result
+17
-10
mysql-test/t/view.test
mysql-test/t/view.test
+16
-19
sql/sql_class.h
sql/sql_class.h
+5
-0
sql/sql_update.cc
sql/sql_update.cc
+113
-30
No files found.
mysql-test/r/view.result
View file @
7b4ed800
...
@@ -3139,16 +3139,6 @@ code COUNT(DISTINCT country)
...
@@ -3139,16 +3139,6 @@ code COUNT(DISTINCT country)
100 2
100 2
DROP VIEW v1;
DROP VIEW v1;
DROP TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 (id int);
CREATE TABLE t2 (id int, c int DEFAULT 0);
INSERT INTO t1 (id) VALUES (1);
INSERT INTO t2 (id) VALUES (1);
CREATE VIEW v1 AS
SELECT t2.c FROM t1, t2
WHERE t1.id=t2.id AND 1 IN (SELECT id FROM t1) WITH CHECK OPTION;
UPDATE v1 SET c=1;
DROP VIEW v1;
DROP TABLE t1,t2;
DROP VIEW IF EXISTS v1;
DROP VIEW IF EXISTS v1;
SELECT * FROM (SELECT 1) AS t;
SELECT * FROM (SELECT 1) AS t;
1
1
...
@@ -3369,6 +3359,23 @@ SHOW CREATE VIEW v1;
...
@@ -3369,6 +3359,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 @
7b4ed800
...
@@ -3055,25 +3055,6 @@ DROP VIEW v1;
...
@@ -3055,25 +3055,6 @@ DROP VIEW v1;
DROP
TABLE
t1
;
DROP
TABLE
t1
;
#
#
#
# Bug #28561: update on multi-table view with CHECK OPTION and
# a subquery in WHERE condition
#
CREATE
TABLE
t1
(
id
int
);
CREATE
TABLE
t2
(
id
int
,
c
int
DEFAULT
0
);
INSERT
INTO
t1
(
id
)
VALUES
(
1
);
INSERT
INTO
t2
(
id
)
VALUES
(
1
);
CREATE
VIEW
v1
AS
SELECT
t2
.
c
FROM
t1
,
t2
WHERE
t1
.
id
=
t2
.
id
AND
1
IN
(
SELECT
id
FROM
t1
)
WITH
CHECK
OPTION
;
UPDATE
v1
SET
c
=
1
;
DROP
VIEW
v1
;
DROP
TABLE
t1
,
t2
;
# BUG#25897: Some queries are no longer possible after a CREATE VIEW
# BUG#25897: Some queries are no longer possible after a CREATE VIEW
# fails
# fails
#
#
...
@@ -3244,6 +3225,22 @@ CREATE VIEW v1 AS SELECT CAST(1.23456789 AS DECIMAL(8,0)) AS col;
...
@@ -3244,6 +3225,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 @
7b4ed800
...
@@ -2273,6 +2273,11 @@ class multi_update :public select_result_interceptor
...
@@ -2273,6 +2273,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 @
7b4ed800
...
@@ -1093,6 +1093,7 @@ int multi_update::prepare(List<Item> ¬_used_values,
...
@@ -1093,6 +1093,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
;
...
@@ -1126,6 +1127,7 @@ int multi_update::prepare(List<Item> ¬_used_values,
...
@@ -1126,6 +1127,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
,
...
@@ -1187,7 +1189,7 @@ int multi_update::prepare(List<Item> ¬_used_values,
...
@@ -1187,7 +1189,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
);
}
}
...
@@ -1278,13 +1280,22 @@ multi_update::initialize_tables(JOIN *join)
...
@@ -1278,13 +1280,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
;
TMP_TABLE_PARAM
*
tmp_param
;
TMP_TABLE_PARAM
*
tmp_param
;
...
@@ -1301,27 +1312,56 @@ multi_update::initialize_tables(JOIN *join)
...
@@ -1301,27 +1312,56 @@ multi_update::initialize_tables(JOIN *join)
}
}
table
->
prepare_for_position
();
table
->
prepare_for_position
();
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_param
=
tmp_table_param
+
cnt
;
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
;
&
my_charset_bin
);
do
offset
.
init
(
table
);
{
Field_string
*
field
=
new
Field_string
(
tbl
->
file
->
ref_length
,
0
,
tbl
->
alias
,
&
my_charset_bin
);
if
(
!
field
)
DBUG_RETURN
(
1
);
field
->
init
(
tbl
);
/*
/*
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
));
...
@@ -1473,11 +1513,26 @@ bool multi_update::send_data(List<Item> ¬_used_values)
...
@@ -1473,11 +1513,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
];
table
->
file
->
position
(
table
->
record
[
0
]);
/*
fill_record
(
thd
,
tmp_table
->
field
+
1
,
*
values_for_table
[
offset
],
1
);
For updatable VIEW store rowid of the updated table and
/* Store pointer to row */
rowids of tables used in the CHECK OPTION condition.
memcpy
((
char
*
)
tmp_table
->
field
[
0
]
->
ptr
,
*/
(
char
*
)
table
->
file
->
ref
,
table
->
file
->
ref_length
);
uint
field_num
=
0
;
List_iterator_fast
<
TABLE
>
tbl_it
(
unupdated_check_opt_tables
);
TABLE
*
tbl
=
table
;
do
{
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
++
));
/* Store regular updated fields in the row. */
fill_record
(
thd
,
tmp_table
->
field
+
1
+
unupdated_check_opt_tables
.
elements
,
*
values_for_table
[
offset
],
1
);
/* Write row, ignoring duplicated updates to a row */
/* Write row, ignoring duplicated updates to a row */
error
=
tmp_table
->
file
->
ha_write_row
(
tmp_table
->
record
[
0
]);
error
=
tmp_table
->
file
->
ha_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
)
...
@@ -1527,9 +1582,10 @@ void multi_update::send_error(uint errcode,const char *err)
...
@@ -1527,9 +1582,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
...
@@ -1537,8 +1593,8 @@ int multi_update::do_updates(bool from_send_error)
...
@@ -1537,8 +1593,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
)
...
@@ -1549,11 +1605,20 @@ int multi_update::do_updates(bool from_send_error)
...
@@ -1549,11 +1605,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
++
)
{
{
...
@@ -1570,7 +1635,6 @@ int multi_update::do_updates(bool from_send_error)
...
@@ -1570,7 +1635,6 @@ int multi_update::do_updates(bool from_send_error)
bitmap_is_subset
(
table
->
write_set
,
bitmap_is_subset
(
table
->
write_set
,
table
->
read_set
));
table
->
read_set
));
ref_pos
=
(
byte
*
)
tmp_table
->
field
[
0
]
->
ptr
;
for
(;;)
for
(;;)
{
{
if
(
thd
->
killed
&&
trans_safe
)
if
(
thd
->
killed
&&
trans_safe
)
...
@@ -1583,8 +1647,20 @@ int multi_update::do_updates(bool from_send_error)
...
@@ -1583,8 +1647,20 @@ 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
],
(
byte
*
)
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
]);
...
@@ -1635,6 +1711,10 @@ int multi_update::do_updates(bool from_send_error)
...
@@ -1635,6 +1711,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
);
...
@@ -1648,6 +1728,9 @@ err:
...
@@ -1648,6 +1728,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