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
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
67fcac7a
Commit
67fcac7a
authored
Sep 15, 2004
by
bell@sanja.is.com.ua
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
support of join view updateability (WL#1809)
parent
f797298f
Changes
38
Hide whitespace changes
Inline
Side-by-side
Showing
38 changed files
with
716 additions
and
101 deletions
+716
-101
include/mysqld_error.h
include/mysqld_error.h
+4
-1
mysql-test/r/view.result
mysql-test/r/view.result
+149
-0
mysql-test/t/view.test
mysql-test/t/view.test
+90
-0
sql/mysql_priv.h
sql/mysql_priv.h
+2
-1
sql/share/czech/errmsg.txt
sql/share/czech/errmsg.txt
+3
-0
sql/share/danish/errmsg.txt
sql/share/danish/errmsg.txt
+3
-0
sql/share/dutch/errmsg.txt
sql/share/dutch/errmsg.txt
+3
-0
sql/share/english/errmsg.txt
sql/share/english/errmsg.txt
+3
-0
sql/share/estonian/errmsg.txt
sql/share/estonian/errmsg.txt
+3
-0
sql/share/french/errmsg.txt
sql/share/french/errmsg.txt
+3
-0
sql/share/german/errmsg.txt
sql/share/german/errmsg.txt
+3
-0
sql/share/greek/errmsg.txt
sql/share/greek/errmsg.txt
+3
-0
sql/share/hungarian/errmsg.txt
sql/share/hungarian/errmsg.txt
+3
-0
sql/share/italian/errmsg.txt
sql/share/italian/errmsg.txt
+3
-0
sql/share/japanese/errmsg.txt
sql/share/japanese/errmsg.txt
+3
-0
sql/share/korean/errmsg.txt
sql/share/korean/errmsg.txt
+3
-0
sql/share/norwegian-ny/errmsg.txt
sql/share/norwegian-ny/errmsg.txt
+3
-0
sql/share/norwegian/errmsg.txt
sql/share/norwegian/errmsg.txt
+3
-0
sql/share/polish/errmsg.txt
sql/share/polish/errmsg.txt
+3
-0
sql/share/portuguese/errmsg.txt
sql/share/portuguese/errmsg.txt
+3
-0
sql/share/romanian/errmsg.txt
sql/share/romanian/errmsg.txt
+3
-0
sql/share/russian/errmsg.txt
sql/share/russian/errmsg.txt
+4
-1
sql/share/serbian/errmsg.txt
sql/share/serbian/errmsg.txt
+3
-0
sql/share/slovak/errmsg.txt
sql/share/slovak/errmsg.txt
+3
-0
sql/share/spanish/errmsg.txt
sql/share/spanish/errmsg.txt
+3
-0
sql/share/swedish/errmsg.txt
sql/share/swedish/errmsg.txt
+3
-0
sql/share/ukrainian/errmsg.txt
sql/share/ukrainian/errmsg.txt
+3
-0
sql/sql_base.cc
sql/sql_base.cc
+1
-1
sql/sql_class.h
sql/sql_class.h
+6
-3
sql/sql_delete.cc
sql/sql_delete.cc
+8
-1
sql/sql_insert.cc
sql/sql_insert.cc
+113
-30
sql/sql_parse.cc
sql/sql_parse.cc
+36
-20
sql/sql_prepare.cc
sql/sql_prepare.cc
+45
-8
sql/sql_update.cc
sql/sql_update.cc
+67
-13
sql/sql_view.cc
sql/sql_view.cc
+32
-21
sql/sql_view.h
sql/sql_view.h
+1
-1
sql/table.cc
sql/table.cc
+89
-0
sql/table.h
sql/table.h
+3
-0
No files found.
include/mysqld_error.h
View file @
67fcac7a
...
...
@@ -380,4 +380,7 @@
#define ER_TRG_ON_VIEW_OR_TEMP_TABLE 1361
#define ER_TRG_CANT_CHANGE_ROW 1362
#define ER_TRG_NO_SUCH_ROW_IN_TRG 1363
#define ER_ERROR_MESSAGES 364
#define ER_VIEW_MULTIUPDATE 1364
#define ER_VIEW_NO_INSERT_FIELD_LIST 1365
#define ER_VIEW_DELETE_MERGE_VIEW 1366
#define ER_ERROR_MESSAGES 367
mysql-test/r/view.result
View file @
67fcac7a
...
...
@@ -1359,3 +1359,152 @@ a a b
deallocate prepare stmt1;
drop view v4,v3,v2,v1;
drop tables t1,t2,t3;
create table t1 (a int, primary key (a), b int);
create table t2 (a int, primary key (a));
insert into t1 values (1,100), (2,200);
insert into t2 values (1), (3);
create view v3 (a,b) as select t1.a as a, t2.a as b from t1, t2;
update v3 set a= 10 where a=1;
select * from t1;
a b
10 100
2 200
select * from t2;
a
1
3
create view v2 (a,b) as select t1.b as a, t2.a as b from t1, t2;
update v2 set a= 10 where a=200;
ERROR HY000: The target table v2 of the UPDATE is not updatable
select * from v3;
a b
2 1
10 1
2 3
10 3
select * from v2;
a b
100 1
200 1
100 3
200 3
set @a= 10;
set @b= 100;
prepare stmt1 from "update v3 set a= ? where a=?";
execute stmt1 using @a,@b;
select * from v3;
a b
2 1
10 1
2 3
10 3
set @a= 300;
set @b= 10;
execute stmt1 using @a,@b;
select * from v3;
a b
2 1
300 1
2 3
300 3
deallocate prepare stmt1;
drop view v3,v2;
drop tables t1,t2;
create table t1 (a int, primary key (a), b int);
create table t2 (a int, primary key (a), b int);
insert into t2 values (1000, 2000);
create view v3 (a,b) as select t1.a as a, t2.a as b from t1, t2;
insert into v3 values (1,2);
ERROR HY000: Can not insert into join view 'test.v3' without fields list
insert into v3 select * from t2;
ERROR HY000: Can not insert into join view 'test.v3' without fields list
insert into v3(a,b) values (1,2);
ERROR HY000: Can not modify more than one base table through a join view 'test.v3'
insert into v3(a,b) select * from t2;
ERROR HY000: Can not modify more than one base table through a join view 'test.v3'
insert into v3(a) values (1);
insert into v3(b) values (10);
insert into v3(a) select a from t2;
insert into v3(b) select b from t2;
Warnings:
Warning 1263 Data truncated; NULL supplied to NOT NULL column 'a' at row 2
insert into v3(a) values (1) on duplicate key update a=a+10000+VALUES(a);
select * from t1;
a b
10002 NULL
10 NULL
1000 NULL
select * from t2;
a b
1000 2000
10 NULL
2000 NULL
0 NULL
create view v2 (a,b) as select t1.b as a, t2.a as b from t1, t2;
insert into v2(a) values (10);
ERROR HY000: The target table v2 of the INSERT is not updatable
select * from v3;
a b
10 1000
1000 1000
10002 1000
10 10
1000 10
10002 10
10 2000
1000 2000
10002 2000
10 0
1000 0
10002 0
select * from v2;
a b
NULL 1000
NULL 1000
NULL 1000
NULL 10
NULL 10
NULL 10
NULL 2000
NULL 2000
NULL 2000
NULL 0
NULL 0
NULL 0
delete from v3;
ERROR HY000: Can not delete from join view 'test.v3'
delete v3,t1 from v3,t1;
ERROR HY000: Can not delete from join view 'test.v3'
delete from t1;
prepare stmt1 from "insert into v3(a) values (?);";
set @a= 100;
execute stmt1 using @a;
set @a= 300;
execute stmt1 using @a;
deallocate prepare stmt1;
prepare stmt1 from "insert into v3(a) select ?;";
set @a= 101;
execute stmt1 using @a;
set @a= 301;
execute stmt1 using @a;
deallocate prepare stmt1;
select * from v3;
a b
100 1000
101 1000
300 1000
301 1000
100 10
101 10
300 10
301 10
100 2000
101 2000
300 2000
301 2000
100 0
101 0
300 0
301 0
drop view v3,v2;
drop tables t1,t2;
mysql-test/t/view.test
View file @
67fcac7a
...
...
@@ -1298,3 +1298,93 @@ execute stmt1;
deallocate
prepare
stmt1
;
drop
view
v4
,
v3
,
v2
,
v1
;
drop
tables
t1
,
t2
,
t3
;
#
# updating of join view
#
create
table
t1
(
a
int
,
primary
key
(
a
),
b
int
);
create
table
t2
(
a
int
,
primary
key
(
a
));
insert
into
t1
values
(
1
,
100
),
(
2
,
200
);
insert
into
t2
values
(
1
),
(
3
);
# legal view for update
create
view
v3
(
a
,
b
)
as
select
t1
.
a
as
a
,
t2
.
a
as
b
from
t1
,
t2
;
update
v3
set
a
=
10
where
a
=
1
;
select
*
from
t1
;
select
*
from
t2
;
# view without primary key
create
view
v2
(
a
,
b
)
as
select
t1
.
b
as
a
,
t2
.
a
as
b
from
t1
,
t2
;
--
error
1288
update
v2
set
a
=
10
where
a
=
200
;
# just view selects
select
*
from
v3
;
select
*
from
v2
;
# prepare statement with updating join view
set
@
a
=
10
;
set
@
b
=
100
;
prepare
stmt1
from
"update v3 set a= ? where a=?"
;
execute
stmt1
using
@
a
,
@
b
;
select
*
from
v3
;
set
@
a
=
300
;
set
@
b
=
10
;
execute
stmt1
using
@
a
,
@
b
;
select
*
from
v3
;
deallocate
prepare
stmt1
;
drop
view
v3
,
v2
;
drop
tables
t1
,
t2
;
#
# inserting/deleting join view
#
create
table
t1
(
a
int
,
primary
key
(
a
),
b
int
);
create
table
t2
(
a
int
,
primary
key
(
a
),
b
int
);
insert
into
t2
values
(
1000
,
2000
);
create
view
v3
(
a
,
b
)
as
select
t1
.
a
as
a
,
t2
.
a
as
b
from
t1
,
t2
;
# inserting into join view without field list
--
error
1365
insert
into
v3
values
(
1
,
2
);
--
error
1365
insert
into
v3
select
*
from
t2
;
# inserting in several tables of join view
--
error
1364
insert
into
v3
(
a
,
b
)
values
(
1
,
2
);
--
error
1364
insert
into
v3
(
a
,
b
)
select
*
from
t2
;
# correct inserts into join view
insert
into
v3
(
a
)
values
(
1
);
insert
into
v3
(
b
)
values
(
10
);
insert
into
v3
(
a
)
select
a
from
t2
;
insert
into
v3
(
b
)
select
b
from
t2
;
insert
into
v3
(
a
)
values
(
1
)
on
duplicate
key
update
a
=
a
+
10000
+
VALUES
(
a
);
select
*
from
t1
;
select
*
from
t2
;
# view without primary key
create
view
v2
(
a
,
b
)
as
select
t1
.
b
as
a
,
t2
.
a
as
b
from
t1
,
t2
;
--
error
1288
insert
into
v2
(
a
)
values
(
10
);
# just view selects
select
*
from
v3
;
select
*
from
v2
;
# try delete from join view
--
error
1366
delete
from
v3
;
--
error
1366
delete
v3
,
t1
from
v3
,
t1
;
# delete from t1 just to reduce result set size
delete
from
t1
;
# prepare statement with insert join view
prepare
stmt1
from
"insert into v3(a) values (?);"
;
set
@
a
=
100
;
execute
stmt1
using
@
a
;
set
@
a
=
300
;
execute
stmt1
using
@
a
;
deallocate
prepare
stmt1
;
prepare
stmt1
from
"insert into v3(a) select ?;"
;
set
@
a
=
101
;
execute
stmt1
using
@
a
;
set
@
a
=
301
;
execute
stmt1
using
@
a
;
deallocate
prepare
stmt1
;
select
*
from
v3
;
drop
view
v3
,
v2
;
drop
tables
t1
,
t2
;
sql/mysql_priv.h
View file @
67fcac7a
...
...
@@ -611,7 +611,8 @@ int mysql_multi_update(THD *thd, TABLE_LIST *table_list,
List
<
Item
>
*
fields
,
List
<
Item
>
*
values
,
COND
*
conds
,
ulong
options
,
enum
enum_duplicates
handle_duplicates
,
SELECT_LEX_UNIT
*
unit
,
SELECT_LEX
*
select_lex
);
SELECT_LEX_UNIT
*
unit
,
SELECT_LEX
*
select_lex
,
bool
converted
);
int
mysql_prepare_insert
(
THD
*
thd
,
TABLE_LIST
*
table_list
,
TABLE
*
table
,
List
<
Item
>
&
fields
,
List_item
*
values
,
List
<
Item
>
&
update_fields
,
...
...
sql/share/czech/errmsg.txt
View file @
67fcac7a
...
...
@@ -392,3 +392,6 @@ character-set=latin2
"Trigger's '%-.64s' is view or temporary table"
"Updating of %s row is not allowed in %strigger"
"There is no %s row in %s trigger"
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
"Can not insert into join view '%-.64s.%-.64s' without fields list"
"Can not delete from join view '%-.64s.%-.64s'"
sql/share/danish/errmsg.txt
View file @
67fcac7a
...
...
@@ -383,3 +383,6 @@ character-set=latin1
"Trigger's '%-.64s' is view or temporary table"
"Updating of %s row is not allowed in %strigger"
"There is no %s row in %s trigger"
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
"Can not insert into join view '%-.64s.%-.64s' without fields list"
"Can not delete from join view '%-.64s.%-.64s'"
sql/share/dutch/errmsg.txt
View file @
67fcac7a
...
...
@@ -392,3 +392,6 @@ character-set=latin1
"Trigger's '%-.64s' is view or temporary table"
"Updating of %s row is not allowed in %strigger"
"There is no %s row in %s trigger"
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
"Can not insert into join view '%-.64s.%-.64s' without fields list"
"Can not delete from join view '%-.64s.%-.64s'"
sql/share/english/errmsg.txt
View file @
67fcac7a
...
...
@@ -380,3 +380,6 @@ character-set=latin1
"Trigger's '%-.64s' is view or temporary table"
"Updating of %s row is not allowed in %strigger"
"There is no %s row in %s trigger"
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
"Can not insert into join view '%-.64s.%-.64s' without fields list"
"Can not delete from join view '%-.64s.%-.64s'"
sql/share/estonian/errmsg.txt
View file @
67fcac7a
...
...
@@ -385,3 +385,6 @@ character-set=latin7
"Trigger's '%-.64s' is view or temporary table"
"Updating of %s row is not allowed in %strigger"
"There is no %s row in %s trigger"
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
"Can not insert into join view '%-.64s.%-.64s' without fields list"
"Can not delete from join view '%-.64s.%-.64s'"
sql/share/french/errmsg.txt
View file @
67fcac7a
...
...
@@ -380,3 +380,6 @@ character-set=latin1
"Trigger's '%-.64s' is view or temporary table"
"Updating of %s row is not allowed in %strigger"
"There is no %s row in %s trigger"
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
"Can not insert into join view '%-.64s.%-.64s' without fields list"
"Can not delete from join view '%-.64s.%-.64s'"
sql/share/german/errmsg.txt
View file @
67fcac7a
...
...
@@ -393,3 +393,6 @@ character-set=latin1
"Trigger's '%-.64s' is view or temporary table"
"Updating of %s row is not allowed in %strigger"
"There is no %s row in %s trigger"
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
"Can not insert into join view '%-.64s.%-.64s' without fields list"
"Can not delete from join view '%-.64s.%-.64s'"
sql/share/greek/errmsg.txt
View file @
67fcac7a
...
...
@@ -380,3 +380,6 @@ character-set=greek
"Trigger's '%-.64s' is view or temporary table"
"Updating of %s row is not allowed in %strigger"
"There is no %s row in %s trigger"
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
"Can not insert into join view '%-.64s.%-.64s' without fields list"
"Can not delete from join view '%-.64s.%-.64s'"
sql/share/hungarian/errmsg.txt
View file @
67fcac7a
...
...
@@ -385,3 +385,6 @@ character-set=latin2
"Trigger's '%-.64s' is view or temporary table"
"Updating of %s row is not allowed in %strigger"
"There is no %s row in %s trigger"
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
"Can not insert into join view '%-.64s.%-.64s' without fields list"
"Can not delete from join view '%-.64s.%-.64s'"
sql/share/italian/errmsg.txt
View file @
67fcac7a
...
...
@@ -380,3 +380,6 @@ character-set=latin1
"Trigger's '%-.64s' is view or temporary table"
"Updating of %s row is not allowed in %strigger"
"There is no %s row in %s trigger"
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
"Can not insert into join view '%-.64s.%-.64s' without fields list"
"Can not delete from join view '%-.64s.%-.64s'"
sql/share/japanese/errmsg.txt
View file @
67fcac7a
...
...
@@ -384,3 +384,6 @@ character-set=ujis
"Trigger's '%-.64s' is view or temporary table"
"Updating of %s row is not allowed in %strigger"
"There is no %s row in %s trigger"
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
"Can not insert into join view '%-.64s.%-.64s' without fields list"
"Can not delete from join view '%-.64s.%-.64s'"
sql/share/korean/errmsg.txt
View file @
67fcac7a
...
...
@@ -380,3 +380,6 @@ character-set=euckr
"Trigger's '%-.64s' is view or temporary table"
"Updating of %s row is not allowed in %strigger"
"There is no %s row in %s trigger"
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
"Can not insert into join view '%-.64s.%-.64s' without fields list"
"Can not delete from join view '%-.64s.%-.64s'"
sql/share/norwegian-ny/errmsg.txt
View file @
67fcac7a
...
...
@@ -382,3 +382,6 @@ character-set=latin1
"Trigger's '%-.64s' is view or temporary table"
"Updating of %s row is not allowed in %strigger"
"There is no %s row in %s trigger"
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
"Can not insert into join view '%-.64s.%-.64s' without fields list"
"Can not delete from join view '%-.64s.%-.64s'"
sql/share/norwegian/errmsg.txt
View file @
67fcac7a
...
...
@@ -382,3 +382,6 @@ character-set=latin1
"Trigger's '%-.64s' is view or temporary table"
"Updating of %s row is not allowed in %strigger"
"There is no %s row in %s trigger"
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
"Can not insert into join view '%-.64s.%-.64s' without fields list"
"Can not delete from join view '%-.64s.%-.64s'"
sql/share/polish/errmsg.txt
View file @
67fcac7a
...
...
@@ -385,3 +385,6 @@ character-set=latin2
"Trigger's '%-.64s' is view or temporary table"
"Updating of %s row is not allowed in %strigger"
"There is no %s row in %s trigger"
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
"Can not insert into join view '%-.64s.%-.64s' without fields list"
"Can not delete from join view '%-.64s.%-.64s'"
sql/share/portuguese/errmsg.txt
View file @
67fcac7a
...
...
@@ -382,3 +382,6 @@ character-set=latin1
"Trigger's '%-.64s' is view or temporary table"
"Updating of %s row is not allowed in %strigger"
"There is no %s row in %s trigger"
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
"Can not insert into join view '%-.64s.%-.64s' without fields list"
"Can not delete from join view '%-.64s.%-.64s'"
sql/share/romanian/errmsg.txt
View file @
67fcac7a
...
...
@@ -385,3 +385,6 @@ character-set=latin2
"Trigger's '%-.64s' is view or temporary table"
"Updating of %s row is not allowed in %strigger"
"There is no %s row in %s trigger"
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
"Can not insert into join view '%-.64s.%-.64s' without fields list"
"Can not delete from join view '%-.64s.%-.64s'"
sql/share/russian/errmsg.txt
View file @
67fcac7a
...
...
@@ -376,7 +376,7 @@ character-set=koi8r
"View SELECT '%-.64s'"
"View SELECT view "
" view ( )"
" view ()"
" view
()
()"
"View '%-.64s.%-.64s' "
"Can't drop a %s from within another stored routine"
"GOTO is not allowed in a stored procedure handler"
...
...
@@ -385,3 +385,6 @@ character-set=koi8r
"Trigger's '%-.64s' is view or temporary table"
"Updating of %s row is not allowed in %strigger"
"There is no %s row in %s trigger"
" VIEW '%-.64s.%-.64s'"
" VIEW '%-.64s.%-.64s' "
" VIEW '%-.64s.%-.64s'"
sql/share/serbian/errmsg.txt
View file @
67fcac7a
...
...
@@ -373,3 +373,6 @@ character-set=cp1250
"Trigger's '%-.64s' is view or temporary table"
"Updating of %s row is not allowed in %strigger"
"There is no %s row in %s trigger"
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
"Can not insert into join view '%-.64s.%-.64s' without fields list"
"Can not delete from join view '%-.64s.%-.64s'"
sql/share/slovak/errmsg.txt
View file @
67fcac7a
...
...
@@ -388,3 +388,6 @@ character-set=latin2
"Trigger's '%-.64s' is view or temporary table"
"Updating of %s row is not allowed in %strigger"
"There is no %s row in %s trigger"
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
"Can not insert into join view '%-.64s.%-.64s' without fields list"
"Can not delete from join view '%-.64s.%-.64s'"
sql/share/spanish/errmsg.txt
View file @
67fcac7a
...
...
@@ -384,3 +384,6 @@ character-set=latin1
"Trigger's '%-.64s' is view or temporary table"
"Updating of %s row is not allowed in %strigger"
"There is no %s row in %s trigger"
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
"Can not insert into join view '%-.64s.%-.64s' without fields list"
"Can not delete from join view '%-.64s.%-.64s'"
sql/share/swedish/errmsg.txt
View file @
67fcac7a
...
...
@@ -380,3 +380,6 @@ character-set=latin1
"Trigger's '%-.64s' is view or temporary table"
"Updating of %s row is not allowed in %strigger"
"There is no %s row in %s trigger"
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
"Can not insert into join view '%-.64s.%-.64s' without fields list"
"Can not delete from join view '%-.64s.%-.64s'"
sql/share/ukrainian/errmsg.txt
View file @
67fcac7a
...
...
@@ -386,3 +386,6 @@ character-set=koi8u
"Trigger's '%-.64s' is view or temporary table"
"Updating of %s row is not allowed in %strigger"
"There is no %s row in %s trigger"
" ¦ VIEW '%-.64s.%-.64s', ͦԦ ˦ "
" VIEW '%-.64s.%-.64s', ͦ ˦ , æ"
" VIEW '%-.64s.%-.64s', ͦ ˦ "
sql/sql_base.cc
View file @
67fcac7a
...
...
@@ -2296,7 +2296,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
bool
allow_rowid
=
tables
&&
!
tables
->
next_local
;
// Only one table
for
(;
tables
;
tables
=
tables
->
next_local
)
{
if
(
!
tables
->
table
)
if
(
!
tables
->
table
&&
!
tables
->
ancestor
)
{
if
(
report_error
)
my_printf_error
(
ER_BAD_FIELD_ERROR
,
ER
(
ER_BAD_FIELD_ERROR
),
MYF
(
0
),
...
...
sql/sql_class.h
View file @
67fcac7a
...
...
@@ -1504,7 +1504,9 @@ class multi_delete :public select_result
class
multi_update
:
public
select_result
{
TABLE_LIST
*
all_tables
,
*
update_tables
,
*
table_being_updated
;
TABLE_LIST
*
all_tables
;
/* query/update command tables */
TABLE_LIST
*
leaves
;
/* list of leves of join table tree */
TABLE_LIST
*
update_tables
,
*
table_being_updated
;
THD
*
thd
;
TABLE
**
tmp_tables
,
*
main_table
,
*
table_to_update
;
TMP_TABLE_PARAM
*
tmp_table_param
;
...
...
@@ -1517,8 +1519,9 @@ class multi_update :public select_result
bool
do_update
,
trans_safe
,
transactional_tables
,
log_delayed
;
public:
multi_update
(
THD
*
thd_arg
,
TABLE_LIST
*
ut
,
List
<
Item
>
*
fields
,
List
<
Item
>
*
values
,
enum_duplicates
handle_duplicates
);
multi_update
(
THD
*
thd_arg
,
TABLE_LIST
*
ut
,
TABLE_LIST
*
leaves_list
,
List
<
Item
>
*
fields
,
List
<
Item
>
*
values
,
enum_duplicates
handle_duplicates
);
~
multi_update
();
int
prepare
(
List
<
Item
>
&
list
,
SELECT_LEX_UNIT
*
u
);
bool
send_fields
(
List
<
Item
>
&
list
,
uint
flags
)
{
return
0
;
}
...
...
sql/sql_delete.cc
View file @
67fcac7a
...
...
@@ -43,7 +43,14 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order,
if
((
error
=
open_and_lock_tables
(
thd
,
table_list
)))
DBUG_RETURN
(
error
);
table
=
table_list
->
table
;
if
(
!
(
table
=
table_list
->
table
))
{
DBUG_ASSERT
(
table_list
->
view
&&
table_list
->
ancestor
&&
table_list
->
ancestor
->
next_local
);
my_error
(
ER_VIEW_DELETE_MERGE_VIEW
,
MYF
(
0
),
table_list
->
view_db
.
str
,
table_list
->
view_name
.
str
);
DBUG_RETURN
(
-
1
);
}
table
->
file
->
info
(
HA_STATUS_VARIABLE
|
HA_STATUS_NO_LOCK
);
thd
->
proc_info
=
"init"
;
table
->
map
=
1
;
...
...
sql/sql_insert.cc
View file @
67fcac7a
...
...
@@ -21,6 +21,7 @@
#include "sql_acl.h"
#include "sp_head.h"
#include "sql_trigger.h"
#include "sql_select.h"
static
int
check_null_fields
(
THD
*
thd
,
TABLE
*
entry
);
#ifndef EMBEDDED_LIBRARY
...
...
@@ -31,6 +32,7 @@ static void end_delayed_insert(THD *thd);
extern
"C"
pthread_handler_decl
(
handle_delayed_insert
,
arg
);
static
void
unlink_blobs
(
register
TABLE
*
table
);
#endif
static
bool
check_view_insertability
(
TABLE_LIST
*
view
,
ulong
query_id
);
/* Define to force use of my_malloc() if the allocated memory block is big */
...
...
@@ -54,8 +56,22 @@ check_insert_fields(THD *thd, TABLE_LIST *table_list, List<Item> &fields,
{
TABLE
*
table
=
table_list
->
table
;
if
(
!
table_list
->
updatable
)
{
my_error
(
ER_NON_UPDATABLE_TABLE
,
MYF
(
0
),
table_list
->
alias
,
"INSERT"
);
return
-
1
;
}
if
(
fields
.
elements
==
0
&&
values
.
elements
!=
0
)
{
if
(
!
table
)
{
DBUG_ASSERT
(
table_list
->
view
&&
table_list
->
ancestor
&&
table_list
->
ancestor
->
next_local
);
my_error
(
ER_VIEW_NO_INSERT_FIELD_LIST
,
MYF
(
0
),
table_list
->
view_db
.
str
,
table_list
->
view_name
.
str
);
return
-
1
;
}
if
(
values
.
elements
!=
table
->
fields
)
{
my_printf_error
(
ER_WRONG_VALUE_COUNT_ON_ROW
,
...
...
@@ -97,6 +113,23 @@ check_insert_fields(THD *thd, TABLE_LIST *table_list, List<Item> &fields,
thd
->
lex
->
select_lex
.
no_wrap_view_item
=
0
;
if
(
res
)
return
-
1
;
if
(
table
==
0
)
{
/* it is join view => we need to find table for update */
List_iterator_fast
<
Item
>
it
(
fields
);
Item
*
item
;
TABLE_LIST
*
tbl
=
0
;
table_map
map
=
0
;
while
(
item
=
it
++
)
map
|=
item
->
used_tables
();
if
(
table_list
->
check_single_table
(
&
tbl
,
map
)
||
tbl
==
0
)
{
my_error
(
ER_VIEW_MULTIUPDATE
,
MYF
(
0
),
table_list
->
view_db
.
str
,
table_list
->
view_name
.
str
);
return
-
1
;
}
table_list
->
table
=
table
=
tbl
->
table
;
}
if
(
check_unique
&&
thd
->
dupp_field
)
{
...
...
@@ -111,6 +144,15 @@ check_insert_fields(THD *thd, TABLE_LIST *table_list, List<Item> &fields,
#ifndef NO_EMBEDDED_ACCESS_CHECKS
table
->
grant
.
want_privilege
=
(
SELECT_ACL
&
~
table
->
grant
.
privilege
);
#endif
if
(
check_key_in_view
(
thd
,
table_list
)
||
(
table_list
->
view
&&
check_view_insertability
(
table_list
,
thd
->
query_id
)))
{
my_error
(
ER_NON_UPDATABLE_TABLE
,
MYF
(
0
),
table_list
->
alias
,
"INSERT"
);
return
-
1
;
}
return
0
;
}
...
...
@@ -134,7 +176,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
ulong
counter
=
1
;
ulonglong
id
;
COPY_INFO
info
;
TABLE
*
table
;
TABLE
*
table
=
0
;
List_iterator_fast
<
List_item
>
its
(
values_list
);
List_item
*
values
;
#ifndef EMBEDDED_LIBRARY
...
...
@@ -201,17 +243,14 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
if
(
res
||
thd
->
is_fatal_error
)
DBUG_RETURN
(
-
1
);
table
=
table_list
->
table
;
thd
->
proc_info
=
"init"
;
thd
->
used_tables
=
0
;
values
=
its
++
;
if
(
duplic
==
DUP_UPDATE
&&
!
table
->
insert_values
)
if
(
duplic
==
DUP_UPDATE
)
{
/* it should be allocated before Item::fix_fields() */
table
->
insert_values
=
(
byte
*
)
alloc_root
(
&
thd
->
mem_root
,
table
->
rec_buff_length
);
if
(
!
table
->
insert_values
)
if
(
table_list
->
set_insert_values
(
&
thd
->
mem_root
))
goto
abort
;
}
...
...
@@ -219,6 +258,9 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
update_fields
,
update_values
,
duplic
))
goto
abort
;
/* mysql_prepare_insert set table_list->table if it was not set */
table
=
table_list
->
table
;
// is table which we are changing used somewhere in other parts of query
value_count
=
values
->
elements
;
while
((
values
=
its
++
))
...
...
@@ -437,7 +479,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
::
send_ok
(
thd
,
(
ulong
)
thd
->
row_count_func
,
id
,
buff
);
}
free_underlaid_joins
(
thd
,
&
thd
->
lex
->
select_lex
);
table
->
insert_values
=
0
;
table
_list
->
clear_insert_values
()
;
DBUG_RETURN
(
0
);
abort:
...
...
@@ -446,7 +488,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
end_delayed_insert
(
thd
);
#endif
free_underlaid_joins
(
thd
,
&
thd
->
lex
->
select_lex
);
table
->
insert_values
=
0
;
table
_list
->
clear_insert_values
()
;
DBUG_RETURN
(
-
1
);
}
...
...
@@ -542,11 +584,12 @@ static bool check_view_insertability(TABLE_LIST *view, ulong query_id)
where Pointer to where clause
RETURN
0 ok
1 ERROR
0 ok
1 ERROR and message sent to client
-1 ERROR but message is not sent to client
*/
static
bool
mysql_prepare_insert_check_table
(
THD
*
thd
,
TABLE_LIST
*
table_list
,
static
int
mysql_prepare_insert_check_table
(
THD
*
thd
,
TABLE_LIST
*
table_list
,
List
<
Item
>
&
fields
,
COND
**
where
)
{
bool
insert_into_view
=
(
table_list
->
view
!=
0
);
...
...
@@ -554,22 +597,22 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list,
if
(
setup_tables
(
thd
,
table_list
,
where
,
&
thd
->
lex
->
select_lex
.
leaf_tables
,
0
))
DBUG_RETURN
(
1
);
DBUG_RETURN
(
thd
->
net
.
report_error
?
-
1
:
1
);
if
(
insert_into_view
&&
!
fields
.
elements
)
{
thd
->
lex
->
empty_field_list_on_rset
=
1
;
insert_view_fields
(
&
fields
,
table_list
);
if
(
!
table_list
->
table
)
{
DBUG_ASSERT
(
table_list
->
view
&&
table_list
->
ancestor
&&
table_list
->
ancestor
->
next_local
);
my_error
(
ER_VIEW_NO_INSERT_FIELD_LIST
,
MYF
(
0
),
table_list
->
view_db
.
str
,
table_list
->
view_name
.
str
);
DBUG_RETURN
(
-
1
);
}
DBUG_RETURN
(
insert_view_fields
(
&
fields
,
table_list
));
}
if
(
!
table_list
->
updatable
||
check_key_in_view
(
thd
,
table_list
)
||
(
insert_into_view
&&
check_view_insertability
(
table_list
,
thd
->
query_id
)))
{
my_error
(
ER_NON_UPDATABLE_TABLE
,
MYF
(
0
),
table_list
->
alias
,
"INSERT"
);
DBUG_RETURN
(
1
);
}
DBUG_RETURN
(
0
);
}
...
...
@@ -598,8 +641,9 @@ int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
int
res
;
DBUG_ENTER
(
"mysql_prepare_insert"
);
if
(
mysql_prepare_insert_check_table
(
thd
,
table_list
,
fields
,
&
unused_conds
))
DBUG_RETURN
(
-
1
);
if
((
res
=
mysql_prepare_insert_check_table
(
thd
,
table_list
,
fields
,
&
unused_conds
)))
DBUG_RETURN
(
res
);
if
(
check_insert_fields
(
thd
,
table_list
,
fields
,
*
values
,
1
,
!
insert_into_view
)
||
...
...
@@ -1607,21 +1651,43 @@ bool delayed_insert::handle_inserts(void)
RETURN
0 OK
-1 Error
1 Error sent to client
-1 Error is not sent to client
*/
int
mysql_insert_select_prepare
(
THD
*
thd
)
{
LEX
*
lex
=
thd
->
lex
;
TABLE_LIST
*
first_select_table
=
(
TABLE_LIST
*
)
lex
->
select_lex
.
table_list
.
first
;
TABLE_LIST
*
first_select_leaf_table
;
int
res
;
DBUG_ENTER
(
"mysql_insert_select_prepare"
);
if
(
mysql_prepare_insert_check_table
(
thd
,
lex
->
query_tables
,
lex
->
field_list
,
&
lex
->
select_lex
.
where
))
DBUG_RETURN
(
-
1
);
/* exclude first table from leaf tables list, because it belong to INSERT */
if
((
res
=
mysql_prepare_insert_check_table
(
thd
,
lex
->
query_tables
,
lex
->
field_list
,
&
lex
->
select_lex
.
where
)))
DBUG_RETURN
(
res
);
/*
setup was done in mysql_insert_select_prepare, but we have to mark
first local table
*/
if
(
first_select_table
)
first_select_table
->
setup_is_done
=
1
;
/*
exclude first table from leaf tables list, because it belong to
INSERT
*/
DBUG_ASSERT
(
lex
->
select_lex
.
leaf_tables
);
lex
->
leaf_tables_insert
=
lex
->
select_lex
.
leaf_tables
;
lex
->
select_lex
.
leaf_tables
=
lex
->
select_lex
.
leaf_tables
->
next_leaf
;
/* skip all leaf tables belonged to view where we are insert */
for
(
first_select_leaf_table
=
lex
->
select_lex
.
leaf_tables
->
next_leaf
;
first_select_leaf_table
&&
first_select_leaf_table
->
belong_to_view
&&
first_select_leaf_table
->
belong_to_view
==
lex
->
leaf_tables_insert
->
belong_to_view
;
first_select_leaf_table
=
first_select_leaf_table
->
next_leaf
)
{}
lex
->
select_lex
.
leaf_tables
=
first_select_leaf_table
;
DBUG_RETURN
(
0
);
}
...
...
@@ -1635,6 +1701,23 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
if
(
check_insert_fields
(
thd
,
table_list
,
*
fields
,
values
,
1
,
!
insert_into_view
))
DBUG_RETURN
(
1
);
/*
if it is INSERT into join view then check_insert_fields already found
real table for insert
*/
table
=
table_list
->
table
;
/*
Is table which we are changing used somewhere in other parts of
query
*/
if
(
!
(
thd
->
lex
->
current_select
->
options
&
OPTION_BUFFER_RESULT
)
&&
unique_table
(
table_list
,
table_list
->
next_independent
()))
{
/* Using same table for INSERT and SELECT */
thd
->
lex
->
current_select
->
options
|=
OPTION_BUFFER_RESULT
;
thd
->
lex
->
current_select
->
join
->
select_options
|=
OPTION_BUFFER_RESULT
;
}
restore_record
(
table
,
default_values
);
// Get empty record
table
->
next_number_field
=
table
->
found_next_number_field
;
...
...
sql/sql_parse.cc
View file @
67fcac7a
...
...
@@ -2747,18 +2747,29 @@ mysql_execute_command(THD *thd)
lex
->
duplicates
);
if
(
thd
->
net
.
report_error
)
res
=
-
1
;
break
;
if
(
res
!=
2
)
break
;
case
SQLCOM_UPDATE_MULTI
:
{
bool
converted
=
0
;
DBUG_ASSERT
(
first_table
==
all_tables
&&
first_table
!=
0
);
if
((
res
=
multi_update_precheck
(
thd
,
all_tables
)))
break
;
if
(
res
!=
2
)
{
if
((
res
=
multi_update_precheck
(
thd
,
all_tables
)))
break
;
}
else
{
res
=
0
;
converted
=
1
;
}
res
=
mysql_multi_update
(
thd
,
all_tables
,
&
select_lex
->
item_list
,
&
lex
->
value_list
,
select_lex
->
where
,
select_lex
->
options
,
lex
->
duplicates
,
unit
,
select_lex
);
lex
->
duplicates
,
unit
,
select_lex
,
converted
);
break
;
}
case
SQLCOM_REPLACE
:
...
...
@@ -2796,31 +2807,26 @@ mysql_execute_command(THD *thd)
if
(
!
(
res
=
open_and_lock_tables
(
thd
,
all_tables
)))
{
/*
Is table which we are changing used somewhere in other parts of
query
*/
if
(
unique_table
(
first_table
,
all_tables
->
next_independent
()))
/* Skip first table, which is the table we are inserting in */
lex
->
select_lex
.
table_list
.
first
=
(
byte
*
)
first_table
->
next_local
;
res
=
mysql_insert_select_prepare
(
thd
);
if
(
!
res
&&
(
result
=
new
select_insert
(
first_table
,
first_table
->
table
,
&
lex
->
field_list
,
lex
->
duplicates
)))
{
/* Using same table for INSERT and SELECT */
select_lex
->
options
|=
OPTION_BUFFER_RESULT
;
}
TABLE_LIST
*
first_select_table
;
if
((
res
=
mysql_insert_select_prepare
(
thd
)))
break
;
if
((
result
=
new
select_insert
(
first_table
,
first_table
->
table
,
&
lex
->
field_list
,
lex
->
duplicates
)))
/* Skip first table, which is the table we are inserting in */
lex
->
select_lex
.
table_list
.
first
=
(
byte
*
)
first_table
->
next_local
;
/*
insert/replace from SELECT give its SELECT_LEX for SELECT,
and item_list belong to SELECT
*/
lex
->
select_lex
.
resolve_mode
=
SELECT_LEX
::
SELECT_MODE
;
res
=
handle_select
(
thd
,
lex
,
result
);
/* revert changes for SP */
lex
->
select_lex
.
table_list
.
first
=
(
byte
*
)
first_table
;
lex
->
select_lex
.
resolve_mode
=
SELECT_LEX
::
INSERT_MODE
;
}
/* revert changes for SP */
lex
->
select_lex
.
table_list
.
first
=
(
byte
*
)
first_table
;
if
(
thd
->
net
.
report_error
)
res
=
-
1
;
}
...
...
@@ -2884,6 +2890,16 @@ mysql_execute_command(THD *thd)
if
((
res
=
open_and_lock_tables
(
thd
,
all_tables
)))
break
;
if
(
!
first_table
->
table
)
{
DBUG_ASSERT
(
first_table
->
view
&&
first_table
->
ancestor
&&
first_table
->
ancestor
->
next_local
);
my_error
(
ER_VIEW_DELETE_MERGE_VIEW
,
MYF
(
0
),
first_table
->
view_db
.
str
,
first_table
->
view_name
.
str
);
res
=
-
1
;
break
;
}
if
((
res
=
mysql_multi_delete_prepare
(
thd
)))
break
;
...
...
sql/sql_prepare.cc
View file @
67fcac7a
...
...
@@ -959,6 +959,7 @@ static int mysql_test_insert(Prepared_statement *stmt,
RETURN VALUE
0 success
2 convert to multi_update
1 error, sent to client
-1 error, not sent to client
*/
...
...
@@ -975,6 +976,15 @@ static int mysql_test_update(Prepared_statement *stmt,
if
(
!
(
res
=
open_and_lock_tables
(
thd
,
table_list
)))
{
if
(
table_list
->
table
==
0
)
{
DBUG_ASSERT
(
table_list
->
view
&&
table_list
->
ancestor
&&
table_list
->
ancestor
->
next_local
);
stmt
->
lex
->
sql_command
=
SQLCOM_UPDATE_MULTI
;
DBUG_PRINT
(
"info"
,
(
"Switch to multi-update (command replaced)"
));
/* convert to multiupdate */
return
2
;
}
if
(
!
(
res
=
mysql_prepare_update
(
thd
,
table_list
,
&
select
->
where
,
select
->
order_list
.
elements
,
...
...
@@ -1027,6 +1037,15 @@ static int mysql_test_delete(Prepared_statement *stmt,
if
(
!
(
res
=
open_and_lock_tables
(
thd
,
table_list
)))
{
if
(
!
table_list
->
table
)
{
DBUG_ASSERT
(
table_list
->
view
&&
table_list
->
ancestor
&&
table_list
->
ancestor
->
next_local
);
my_error
(
ER_VIEW_DELETE_MERGE_VIEW
,
MYF
(
0
),
table_list
->
view_db
.
str
,
table_list
->
view_name
.
str
);
DBUG_RETURN
(
-
1
);
}
res
=
mysql_prepare_delete
(
thd
,
table_list
,
&
lex
->
select_lex
.
where
);
lex
->
unit
.
cleanup
();
}
...
...
@@ -1219,7 +1238,10 @@ static int select_like_statement_test(Prepared_statement *stmt,
LEX
*
lex
=
stmt
->
lex
;
int
res
=
0
;
if
(
tables
&&
(
res
=
open_and_lock_tables
(
thd
,
tables
)))
/* check that tables was not opened during conversion from usual update */
if
(
tables
&&
(
!
tables
->
table
&&
!
tables
->
view
)
&&
(
res
=
open_and_lock_tables
(
thd
,
tables
)))
goto
end
;
if
(
specific_prepare
&&
(
res
=
(
*
specific_prepare
)(
thd
)))
...
...
@@ -1285,6 +1307,7 @@ static int mysql_test_create_table(Prepared_statement *stmt)
mysql_test_multiupdate()
stmt prepared statemen handler
tables list of tables queries
converted converted to multi-update from usual update
RETURN VALUE
0 success
...
...
@@ -1292,10 +1315,11 @@ static int mysql_test_create_table(Prepared_statement *stmt)
-1 error, not sent to client
*/
static
int
mysql_test_multiupdate
(
Prepared_statement
*
stmt
,
TABLE_LIST
*
tables
)
TABLE_LIST
*
tables
,
bool
converted
)
{
int
res
;
if
((
res
=
multi_update_precheck
(
stmt
->
thd
,
tables
)))
if
(
!
converted
&&
(
res
=
multi_update_precheck
(
stmt
->
thd
,
tables
)))
return
res
;
return
select_like_statement_test
(
stmt
,
tables
,
&
mysql_multi_update_prepare
);
}
...
...
@@ -1325,7 +1349,19 @@ static int mysql_test_multidelete(Prepared_statement *stmt,
uint
fake_counter
;
if
((
res
=
multi_delete_precheck
(
stmt
->
thd
,
tables
,
&
fake_counter
)))
return
res
;
return
select_like_statement_test
(
stmt
,
tables
,
&
mysql_multi_delete_prepare
);
if
((
res
=
select_like_statement_test
(
stmt
,
tables
,
&
mysql_multi_delete_prepare
)))
return
res
;
if
(
!
tables
->
table
)
{
DBUG_ASSERT
(
tables
->
view
&&
tables
->
ancestor
&&
tables
->
ancestor
->
next_local
);
my_error
(
ER_VIEW_DELETE_MERGE_VIEW
,
MYF
(
0
),
tables
->
view_db
.
str
,
tables
->
view_name
.
str
);
return
-
1
;
}
return
0
;
}
...
...
@@ -1404,6 +1440,11 @@ static int send_prepare_results(Prepared_statement *stmt, bool text_protocol)
case
SQLCOM_UPDATE
:
res
=
mysql_test_update
(
stmt
,
tables
);
if
(
res
!=
2
)
break
;
case
SQLCOM_UPDATE_MULTI
:
res
=
mysql_test_multiupdate
(
stmt
,
tables
,
res
==
2
);
break
;
case
SQLCOM_DELETE
:
...
...
@@ -1431,10 +1472,6 @@ static int send_prepare_results(Prepared_statement *stmt, bool text_protocol)
case
SQLCOM_DELETE_MULTI
:
res
=
mysql_test_multidelete
(
stmt
,
tables
);
break
;
case
SQLCOM_UPDATE_MULTI
:
res
=
mysql_test_multiupdate
(
stmt
,
tables
);
break
;
case
SQLCOM_INSERT_SELECT
:
res
=
mysql_test_insert_select
(
stmt
,
tables
);
...
...
sql/sql_update.cc
View file @
67fcac7a
...
...
@@ -87,6 +87,28 @@ static bool check_fields(THD *thd, List<Item> &items)
}
/*
Process usual UPDATE
SYNOPSIS
mysql_update()
thd thread handler
fields fields for update
values values of fields for update
conds WHERE clause expression
order_num number of elemen in ORDER BY clause
order ORDER BY clause list
limit limit clause
handle_duplicates how to handle duplicates
RETURN
0 - OK
2 - privilege check and openning table passed, but we need to convert to
multi-update because of view substitution
1 - error and error sent to client
-1 - error and error is not sent to client
*/
int
mysql_update
(
THD
*
thd
,
TABLE_LIST
*
table_list
,
List
<
Item
>
&
fields
,
...
...
@@ -96,7 +118,7 @@ int mysql_update(THD *thd,
ha_rows
limit
,
enum
enum_duplicates
handle_duplicates
)
{
bool
using_limit
=
limit
!=
HA_POS_ERROR
;
bool
using_limit
=
limit
!=
HA_POS_ERROR
;
bool
safe_update
=
thd
->
options
&
OPTION_SAFE_UPDATES
;
bool
used_key_is_modified
,
transactional_table
,
log_delayed
;
int
error
=
0
;
...
...
@@ -117,6 +139,15 @@ int mysql_update(THD *thd,
if
((
error
=
open_and_lock_tables
(
thd
,
table_list
)))
DBUG_RETURN
(
error
);
if
(
table_list
->
table
==
0
)
{
DBUG_ASSERT
(
table_list
->
view
&&
table_list
->
ancestor
&&
table_list
->
ancestor
->
next_local
);
DBUG_PRINT
(
"info"
,
(
"Switch to multi-update"
));
/* convert to multiupdate */
return
2
;
}
thd
->
proc_info
=
"init"
;
table
=
table_list
->
table
;
table
->
file
->
info
(
HA_STATUS_VARIABLE
|
HA_STATUS_NO_LOCK
);
...
...
@@ -626,12 +657,30 @@ int mysql_multi_update_prepare(THD *thd)
if
(
tables_for_update
&
readonly_tables
)
{
// find readonly table/view which cause error
for
(
tl
=
leaves
;
tl
;
tl
=
tl
->
next_l
ocal
)
for
(
tl
=
leaves
;
tl
;
tl
=
tl
->
next_l
eaf
)
{
if
((
readonly_tables
&
tl
->
table
->
map
)
&&
(
tables_for_update
&
tl
->
table
->
map
))
{
my_error
(
ER_NON_UPDATABLE_TABLE
,
MYF
(
0
),
tl
->
alias
,
"UPDATE"
);
TABLE_LIST
*
table
=
tl
->
belong_to_view
?
tl
->
belong_to_view
:
tl
;
my_error
(
ER_NON_UPDATABLE_TABLE
,
MYF
(
0
),
table
->
alias
,
"UPDATE"
);
DBUG_RETURN
(
-
1
);
}
}
}
/* check single table update for view compound from several tables */
for
(
tl
=
table_list
;
tl
;
tl
=
tl
->
next_local
)
{
if
(
tl
->
table
==
0
)
{
DBUG_ASSERT
(
tl
->
view
&&
tl
->
ancestor
&&
tl
->
ancestor
->
next_local
);
TABLE_LIST
*
for_update
=
0
;
if
(
tl
->
check_single_table
(
&
for_update
,
tables_for_update
))
{
my_error
(
ER_VIEW_MULTIUPDATE
,
MYF
(
0
),
tl
->
view_db
.
str
,
tl
->
view_name
.
str
);
DBUG_RETURN
(
-
1
);
}
}
...
...
@@ -647,19 +696,22 @@ int mysql_multi_update(THD *thd,
COND
*
conds
,
ulong
options
,
enum
enum_duplicates
handle_duplicates
,
SELECT_LEX_UNIT
*
unit
,
SELECT_LEX
*
select_lex
)
SELECT_LEX_UNIT
*
unit
,
SELECT_LEX
*
select_lex
,
bool
converted
)
{
int
res
;
int
res
=
0
;
multi_update
*
result
;
DBUG_ENTER
(
"mysql_multi_update"
);
if
((
res
=
open_and_lock_tables
(
thd
,
table_list
)))
if
(
!
converted
&&
(
res
=
open_and_lock_tables
(
thd
,
table_list
)))
DBUG_RETURN
(
res
);
if
((
res
=
mysql_multi_update_prepare
(
thd
)))
DBUG_RETURN
(
res
);
if
(
!
(
result
=
new
multi_update
(
thd
,
table_list
,
fields
,
values
,
if
(
!
(
result
=
new
multi_update
(
thd
,
table_list
,
thd
->
lex
->
select_lex
.
leaf_tables
,
fields
,
values
,
handle_duplicates
)))
DBUG_RETURN
(
-
1
);
...
...
@@ -677,12 +729,14 @@ int mysql_multi_update(THD *thd,
multi_update
::
multi_update
(
THD
*
thd_arg
,
TABLE_LIST
*
table_list
,
TABLE_LIST
*
leaves_list
,
List
<
Item
>
*
field_list
,
List
<
Item
>
*
value_list
,
enum
enum_duplicates
handle_duplicates_arg
)
:
all_tables
(
table_list
),
update_tables
(
0
),
thd
(
thd_arg
),
tmp_tables
(
0
),
updated
(
0
),
found
(
0
),
fields
(
field_list
),
values
(
value_list
),
table_count
(
0
),
copy_field
(
0
),
handle_duplicates
(
handle_duplicates_arg
),
do_update
(
1
),
trans_safe
(
0
),
transactional_tables
(
1
)
:
all_tables
(
table_list
),
leaves
(
leaves_list
),
update_tables
(
0
),
thd
(
thd_arg
),
tmp_tables
(
0
),
updated
(
0
),
found
(
0
),
fields
(
field_list
),
values
(
value_list
),
table_count
(
0
),
copy_field
(
0
),
handle_duplicates
(
handle_duplicates_arg
),
do_update
(
1
),
trans_safe
(
0
),
transactional_tables
(
1
)
{}
...
...
@@ -730,7 +784,7 @@ int multi_update::prepare(List<Item> ¬_used_values,
*/
update
.
empty
();
for
(
table_ref
=
all_tables
;
table_ref
;
table_ref
=
table_ref
->
next_local
)
for
(
table_ref
=
leaves
;
table_ref
;
table_ref
=
table_ref
->
next_leaf
)
{
/* TODO: add support of view of join support */
TABLE
*
table
=
table_ref
->
table
;
...
...
@@ -800,7 +854,7 @@ int multi_update::prepare(List<Item> ¬_used_values,
which will cause an error when reading a row.
(This issue is mostly relevent for MyISAM tables)
*/
for
(
table_ref
=
all_tables
;
table_ref
;
table_ref
=
table_ref
->
next_local
)
for
(
table_ref
=
leaves
;
table_ref
;
table_ref
=
table_ref
->
next_leaf
)
{
TABLE
*
table
=
table_ref
->
table
;
if
(
!
(
tables_to_update
&
table
->
map
)
&&
...
...
sql/sql_view.cc
View file @
67fcac7a
...
...
@@ -465,23 +465,27 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
if
((
view
->
updatable_view
=
(
can_be_merged
&&
view
->
algorithm
!=
VIEW_ALGORITHM_TMPTABLE
)))
{
if
(
thd
->
lex
->
select_lex
.
table_list
.
elements
>
1
)
view
->
updatable_view
=
0
;
else
// TODO: change here when we will support UNIONs
for
(
TABLE_LIST
*
tbl
=
(
TABLE_LIST
*
)
thd
->
lex
->
select_lex
.
table_list
.
first
;
tbl
;
tbl
=
tbl
->
next_local
)
{
// TODO: change here when we will support UNIONs
for
(
TABLE_LIST
*
tbl
=
(
TABLE_LIST
*
)
thd
->
lex
->
select_lex
.
table_list
.
first
;
tbl
;
tbl
=
tbl
->
next_local
)
if
(
tbl
->
view
&&
!
tbl
->
updatable_view
)
{
if
(
tbl
->
view
&&
!
tbl
->
updatable_view
)
{
view
->
updatable_view
=
0
;
break
;
}
view
->
updatable_view
=
0
;
break
;
}
for
(
TABLE_LIST
*
up
=
tbl
;
up
;
up
=
up
->
embedding
)
{
if
(
up
->
outer_join
)
{
view
->
updatable_view
=
0
;
goto
loop_out
;
}
}
}
}
loop_out:
if
(
sql_create_definition_file
(
&
dir
,
&
file
,
view_file_type
,
(
gptr
)
view
,
view_parameters
,
3
))
{
...
...
@@ -701,9 +705,6 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
old_lex
->
can_use_merged
())
&&
!
old_lex
->
can_not_use_merged
())
{
/*
TODO: support multi tables substitutions
*/
/* lex should contain at least one table */
DBUG_ASSERT
(
view_tables
!=
0
);
...
...
@@ -736,7 +737,6 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
/* multi table view */
if
(
view_tables
->
next_local
)
{
table
->
updatable
=
0
;
/* make nested join structure for view tables */
NESTED_JOIN
*
nested_join
;
if
(
!
(
nested_join
=
table
->
nested_join
=
...
...
@@ -919,14 +919,16 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view)
uint
i
,
elements_in_view
;
DBUG_ENTER
(
"check_key_in_view"
);
if
(
!
view
->
view
)
if
(
!
view
->
view
&&
!
view
->
belong_to_view
)
DBUG_RETURN
(
FALSE
);
/* it is normal table */
table
=
view
->
table
;
if
(
view
->
belong_to_view
)
view
=
view
->
belong_to_view
;
trans
=
view
->
field_translation
;
key_info_end
=
(
key_info
=
table
->
key_info
)
+
table
->
keys
;
elements_in_view
=
view
->
view
->
select_lex
.
item_list
.
elements
;
DBUG_ASSERT
(
view
->
table
!=
0
&&
view
->
field_translation
!=
0
);
DBUG_ASSERT
(
table
!=
0
&&
view
->
field_translation
!=
0
);
/* Loop over all keys to see if a unique-not-null key is used */
for
(;
key_info
!=
key_info_end
;
key_info
++
)
...
...
@@ -1002,21 +1004,30 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view)
insert_view_fields()
list list for insertion
view view for processing
RETURN
0 - OK
-1 - error (is not sent to cliet)
*/
void
insert_view_fields
(
List
<
Item
>
*
list
,
TABLE_LIST
*
view
)
int
insert_view_fields
(
List
<
Item
>
*
list
,
TABLE_LIST
*
view
)
{
uint
elements_in_view
=
view
->
view
->
select_lex
.
item_list
.
elements
;
Field_translator
*
trans
;
DBUG_ENTER
(
"insert_view_fields"
);
if
(
!
(
trans
=
view
->
field_translation
))
DBUG_
VOID_RETURN
;
DBUG_
RETURN
(
0
)
;
for
(
uint
i
=
0
;
i
<
elements_in_view
;
i
++
)
{
if
(
trans
[
i
].
item
->
type
()
==
Item
::
FIELD_ITEM
)
list
->
push_back
(
trans
[
i
].
item
);
else
{
my_error
(
ER_NON_UPDATABLE_TABLE
,
MYF
(
0
),
view
->
alias
,
"INSERT"
);
DBUG_RETURN
(
-
1
);
}
}
DBUG_
VOID_RETURN
;
DBUG_
RETURN
(
0
)
;
}
sql/sql_view.h
View file @
67fcac7a
...
...
@@ -25,7 +25,7 @@ int mysql_drop_view(THD *thd, TABLE_LIST *view, enum_drop_mode drop_mode);
bool
check_key_in_view
(
THD
*
thd
,
TABLE_LIST
*
view
);
void
insert_view_fields
(
List
<
Item
>
*
list
,
TABLE_LIST
*
view
);
int
insert_view_fields
(
List
<
Item
>
*
list
,
TABLE_LIST
*
view
);
frm_type_enum
mysql_frm_type
(
char
*
path
);
...
...
sql/table.cc
View file @
67fcac7a
...
...
@@ -1744,6 +1744,95 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds)
}
/*
Find table in underlaying tables by mask and check that only this
table sbelong to given mask
SYNOPSIS
st_table_list::check_single_table()
table reference on variable where to store found table
(should be 0 on call, to find table, or point to table for
unique test)
map bit mask of tables
RETURN
0 table not found or found only one
1 found several tables
*/
bool
st_table_list
::
check_single_table
(
st_table_list
**
table
,
table_map
map
)
{
for
(
TABLE_LIST
*
tbl
=
ancestor
;
tbl
;
tbl
=
tbl
->
next_local
)
{
if
(
tbl
->
table
)
{
if
(
tbl
->
table
->
map
&
map
)
{
if
(
*
table
)
return
1
;
else
*
table
=
tbl
;
}
}
else
if
(
tbl
->
check_single_table
(
table
,
map
))
return
1
;
}
}
/*
Set insert_values buffer
SYNOPSIS
set_insert_values()
mem_root memory pool for allocating
RETURN
FALSE - OK
TRUE - out of memory
*/
bool
st_table_list
::
set_insert_values
(
MEM_ROOT
*
mem_root
)
{
if
(
table
)
{
if
(
!
table
->
insert_values
&&
!
(
table
->
insert_values
=
(
byte
*
)
alloc_root
(
mem_root
,
table
->
rec_buff_length
)))
return
TRUE
;
}
else
{
DBUG_ASSERT
(
view
&&
ancestor
&&
ancestor
->
next_local
);
for
(
TABLE_LIST
*
tbl
=
ancestor
;
tbl
;
tbl
=
tbl
->
next_local
)
if
(
tbl
->
set_insert_values
(
mem_root
))
return
TRUE
;
}
return
FALSE
;
}
/*
clear insert_values reference
SYNOPSIS
clear_insert_values()
*/
void
st_table_list
::
clear_insert_values
()
{
if
(
table
)
table
->
insert_values
=
0
;
else
{
DBUG_ASSERT
(
view
&&
ancestor
&&
ancestor
->
next_local
);
for
(
TABLE_LIST
*
tbl
=
ancestor
;
tbl
;
tbl
=
tbl
->
next_local
)
tbl
->
clear_insert_values
();
}
}
void
Field_iterator_view
::
set
(
TABLE_LIST
*
table
)
{
ptr
=
table
->
field_translation
;
...
...
sql/table.h
View file @
67fcac7a
...
...
@@ -277,6 +277,9 @@ typedef struct st_table_list
void
print
(
THD
*
thd
,
String
*
str
);
void
save_and_clear_want_privilege
();
void
restore_want_privilege
();
bool
check_single_table
(
st_table_list
**
table
,
table_map
map
);
bool
set_insert_values
(
MEM_ROOT
*
mem_root
);
void
clear_insert_values
();
inline
st_table_list
*
next_independent
()
{
if
(
view
)
...
...
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