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
3d389a03
Commit
3d389a03
authored
Oct 25, 2004
by
bell@sanja.is.com.ua
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fixed detection of updating table on which we select (BUG#6032)
parent
6a46a05a
Changes
10
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
85 additions
and
30 deletions
+85
-30
mysql-test/r/view.result
mysql-test/r/view.result
+13
-0
mysql-test/t/view.test
mysql-test/t/view.test
+17
-1
sql/sql_acl.cc
sql/sql_acl.cc
+7
-1
sql/sql_base.cc
sql/sql_base.cc
+14
-6
sql/sql_delete.cc
sql/sql_delete.cc
+1
-1
sql/sql_insert.cc
sql/sql_insert.cc
+1
-1
sql/sql_parse.cc
sql/sql_parse.cc
+1
-1
sql/sql_update.cc
sql/sql_update.cc
+1
-1
sql/sql_view.cc
sql/sql_view.cc
+30
-10
sql/table.h
sql/table.h
+0
-8
No files found.
mysql-test/r/view.result
View file @
3d389a03
...
...
@@ -1633,3 +1633,16 @@ use mysqltest;
create view v1 as select * from t1;
revoke all privileges on mysqltest.* from mysqltest_1@localhost;
drop database mysqltest;
create table t1 (s1 smallint);
create view v1 as select * from t1 where 20 < (select (s1) from t1);
insert into v1 values (30);
ERROR HY000: The target table v1 of the INSERT is not updatable
create view v2 as select * from t1;
create view v3 as select * from t1 where 20 < (select (s1) from v2);
insert into v3 values (30);
ERROR HY000: The target table v3 of the INSERT is not updatable
create view v4 as select * from v2 where 20 < (select (s1) from t1);
insert into v4 values (30);
ERROR HY000: You can't specify target table 'v4' for update in FROM clause
drop view v4, v3, v2, v1;
drop table t1;
mysql-test/t/view.test
View file @
3d389a03
...
...
@@ -1568,7 +1568,23 @@ connection user1;
use
mysqltest
;
create
view
v1
as
select
*
from
t1
;
connection
root
;
revoke
all
privileges
on
mysqltest
.*
from
mysqltest_1
@
localhost
;
drop
database
mysqltest
;
#
# Trys update table from which we select using views and subqueries
#
create
table
t1
(
s1
smallint
);
create
view
v1
as
select
*
from
t1
where
20
<
(
select
(
s1
)
from
t1
);
--
error
1288
insert
into
v1
values
(
30
);
create
view
v2
as
select
*
from
t1
;
create
view
v3
as
select
*
from
t1
where
20
<
(
select
(
s1
)
from
v2
);
--
error
1288
insert
into
v3
values
(
30
);
create
view
v4
as
select
*
from
v2
where
20
<
(
select
(
s1
)
from
t1
);
--
error
1093
insert
into
v4
values
(
30
);
drop
view
v4
,
v3
,
v2
,
v1
;
drop
table
t1
;
sql/sql_acl.cc
View file @
3d389a03
...
...
@@ -3886,13 +3886,19 @@ int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *wildstr)
void
fill_effective_table_privileges
(
THD
*
thd
,
GRANT_INFO
*
grant
,
const
char
*
db
,
const
char
*
table
)
{
/* --skip-grants */
if
(
!
initialized
)
{
grant
->
privilege
=
~
NO_ACCESS
;
// everything is allowed
return
;
}
/* global privileges */
grant
->
privilege
=
thd
->
master_access
;
/* db privileges */
grant
->
privilege
|=
acl_get
(
thd
->
host
,
thd
->
ip
,
thd
->
priv_user
,
db
,
0
);
/* if privileges ignored (--skip-grant-tables) above is enough */
if
(
!
grant_option
)
return
;
...
...
sql/sql_base.cc
View file @
3d389a03
...
...
@@ -593,7 +593,8 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table,
{
if
((
!
strcmp
(
table
->
db
,
db_name
)
&&
!
strcmp
(
table
->
real_name
,
table_name
))
||
(
table
->
view
&&
(
table
->
view
&&
// it is VIEW and
table
->
table
->
table_cache_key
&&
// it is not temporary table
!
strcmp
(
table
->
table
->
table_cache_key
,
db_name
)
&&
!
strcmp
(
table
->
table
->
table_name
,
table_name
)))
break
;
...
...
@@ -618,6 +619,8 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table,
TABLE_LIST
*
unique_table
(
TABLE_LIST
*
table
,
TABLE_LIST
*
table_list
)
{
DBUG_ENTER
(
"unique_table"
);
DBUG_PRINT
(
"enter"
,
(
"table alias: %s"
,
table
->
alias
));
TABLE_LIST
*
res
;
const
char
*
d_name
=
table
->
db
,
*
t_name
=
table
->
real_name
;
char
d_name_buff
[
MAX_ALIAS_NAME
],
t_name_buff
[
MAX_ALIAS_NAME
];
...
...
@@ -644,13 +647,18 @@ TABLE_LIST* unique_table(TABLE_LIST *table, TABLE_LIST *table_list)
return
0
;
}
}
if
((
res
=
find_table_in_global_list
(
table_list
,
d_name
,
t_name
))
&&
res
->
table
&&
res
->
table
==
table
->
table
)
DBUG_PRINT
(
"info"
,
(
"real table: %s.%s"
,
d_name
,
t_name
));
for
(;;)
{
// we found entry of this table try again.
return
find_table_in_global_list
(
res
->
next_global
,
d_name
,
t_name
);
if
(
!
(
res
=
find_table_in_global_list
(
table_list
,
d_name
,
t_name
))
||
!
res
->
table
||
res
->
table
!=
table
->
table
)
break
;
/* if we found entry of this table try again. */
table_list
=
res
->
next_global
;
DBUG_PRINT
(
"info"
,
(
"found same copy of table"
));
}
return
res
;
DBUG_RETURN
(
res
)
;
}
...
...
sql/sql_delete.cc
View file @
3d389a03
...
...
@@ -293,7 +293,7 @@ int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
my_error
(
ER_NON_UPDATABLE_TABLE
,
MYF
(
0
),
table_list
->
alias
,
"DELETE"
);
DBUG_RETURN
(
-
1
);
}
if
(
unique_table
(
table_list
,
table_list
->
next_
independent
()
))
if
(
unique_table
(
table_list
,
table_list
->
next_
global
))
{
my_error
(
ER_UPDATE_TABLE_USED
,
MYF
(
0
),
table_list
->
real_name
);
DBUG_RETURN
(
-
1
);
...
...
sql/sql_insert.cc
View file @
3d389a03
...
...
@@ -641,7 +641,7 @@ int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
setup_fields
(
thd
,
0
,
table_list
,
update_values
,
0
,
0
,
0
))))
DBUG_RETURN
(
-
1
);
if
(
unique_table
(
table_list
,
table_list
->
next_
independent
()
))
if
(
unique_table
(
table_list
,
table_list
->
next_
global
))
{
my_error
(
ER_UPDATE_TABLE_USED
,
MYF
(
0
),
table_list
->
real_name
);
DBUG_RETURN
(
-
1
);
...
...
sql/sql_parse.cc
View file @
3d389a03
...
...
@@ -2810,7 +2810,7 @@ mysql_execute_command(THD *thd)
Is table which we are changing used somewhere in other parts of
query
*/
if
(
unique_table
(
first_table
,
all_tables
->
next_
independent
()
))
if
(
unique_table
(
first_table
,
all_tables
->
next_
global
))
{
/* Using same table for INSERT and SELECT */
select_lex
->
options
|=
OPTION_BUFFER_RESULT
;
...
...
sql/sql_update.cc
View file @
3d389a03
...
...
@@ -529,7 +529,7 @@ int mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
DBUG_RETURN
(
-
1
);
/* Check that we are not using table that we are updating in a sub select */
if
(
unique_table
(
table_list
,
table_list
->
next_
independent
()
))
if
(
unique_table
(
table_list
,
table_list
->
next_
global
))
{
my_error
(
ER_UPDATE_TABLE_USED
,
MYF
(
0
),
table_list
->
real_name
);
DBUG_RETURN
(
-
1
);
...
...
sql/sql_view.cc
View file @
3d389a03
...
...
@@ -382,6 +382,7 @@ static LEX_STRING view_file_type[]= {{(char*)"VIEW", 4}};
static
int
mysql_register_view
(
THD
*
thd
,
TABLE_LIST
*
view
,
enum_view_create_mode
mode
)
{
LEX
*
lex
=
thd
->
lex
;
char
buff
[
4096
];
String
str
(
buff
,(
uint32
)
sizeof
(
buff
),
system_charset_info
);
char
md5
[
33
];
...
...
@@ -395,7 +396,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
{
ulong
sql_mode
=
thd
->
variables
.
sql_mode
&
MODE_ANSI_QUOTES
;
thd
->
variables
.
sql_mode
&=
~
MODE_ANSI_QUOTES
;
thd
->
lex
->
unit
.
print
(
&
str
);
lex
->
unit
.
print
(
&
str
);
thd
->
variables
.
sql_mode
|=
sql_mode
;
}
str
.
append
(
'\0'
);
...
...
@@ -474,21 +475,21 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
view
->
calc_md5
(
md5
);
view
->
md5
.
str
=
md5
;
view
->
md5
.
length
=
32
;
can_be_merged
=
thd
->
lex
->
can_be_merged
();
if
(
thd
->
lex
->
create_view_algorithm
==
VIEW_ALGORITHM_MERGE
&&
!
thd
->
lex
->
can_be_merged
())
can_be_merged
=
lex
->
can_be_merged
();
if
(
lex
->
create_view_algorithm
==
VIEW_ALGORITHM_MERGE
&&
!
lex
->
can_be_merged
())
{
push_warning
(
thd
,
MYSQL_ERROR
::
WARN_LEVEL_WARN
,
ER_WARN_VIEW_MERGE
,
ER
(
ER_WARN_VIEW_MERGE
));
thd
->
lex
->
create_view_algorithm
=
VIEW_ALGORITHM_UNDEFINED
;
lex
->
create_view_algorithm
=
VIEW_ALGORITHM_UNDEFINED
;
}
view
->
algorithm
=
thd
->
lex
->
create_view_algorithm
;
view
->
with_check
=
thd
->
lex
->
create_view_check
;
view
->
algorithm
=
lex
->
create_view_algorithm
;
view
->
with_check
=
lex
->
create_view_check
;
if
((
view
->
updatable_view
=
(
can_be_merged
&&
view
->
algorithm
!=
VIEW_ALGORITHM_TMPTABLE
)))
{
/* TODO: change here when we will support UNIONs */
for
(
TABLE_LIST
*
tbl
=
(
TABLE_LIST
*
)
thd
->
lex
->
select_lex
.
table_list
.
first
;
for
(
TABLE_LIST
*
tbl
=
(
TABLE_LIST
*
)
lex
->
select_lex
.
table_list
.
first
;
tbl
;
tbl
=
tbl
->
next_local
)
{
...
...
@@ -500,6 +501,26 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
}
}
/*
Check that table of main select do not used in subqueries.
This test can catch only very simple cases of such non-updateable views,
all other will be detected before updating commands execution.
(it is more optimisation then real check)
NOTE: this skip cases of using table via VIEWs, joined VIEWs, VIEWs with
UNION
*/
if
(
view
->
updatable_view
&&
!
lex
->
select_lex
.
next_select
()
&&
!
((
TABLE_LIST
*
)
lex
->
select_lex
.
table_list
.
first
)
->
next_local
&&
find_table_in_global_list
(
lex
->
query_tables
->
next_global
,
lex
->
query_tables
->
db
,
lex
->
query_tables
->
real_name
))
{
view
->
updatable_view
=
0
;
}
if
(
view
->
with_check
!=
VIEW_CHECK_NONE
&&
!
view
->
updatable_view
)
{
...
...
@@ -698,13 +719,12 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
tables just after VIEW instead of tail of list, to be able check that
table is unique. Also we store old next table for the same purpose.
*/
table
->
old_next
=
table
->
next_global
;
if
(
view_tables
)
{
if
(
table
->
next_global
)
{
view_tables_tail
->
next_global
=
table
->
next_global
;
table
->
next_global
->
prev_global
=
&
view_tables_tail
->
next_global
;
view_tables_tail
->
next_global
=
table
->
old_next
;
}
else
{
...
...
sql/table.h
View file @
3d389a03
...
...
@@ -232,8 +232,6 @@ typedef struct st_table_list
st_table_list
*
ancestor
;
/* most upper view this table belongs to */
st_table_list
*
belong_to_view
;
/* next_global before adding VIEW tables */
st_table_list
*
old_next
;
Item
*
where
;
/* VIEW WHERE clause condition */
Item
*
check_option
;
/* WITH CHECK OPTION condition */
LEX_STRING
query
;
/* text of (CRETE/SELECT) statement */
...
...
@@ -286,12 +284,6 @@ typedef struct st_table_list
bool
setup_ancestor
(
THD
*
thd
,
Item
**
conds
,
uint8
check_option
);
bool
placeholder
()
{
return
derived
||
view
;
}
void
print
(
THD
*
thd
,
String
*
str
);
inline
st_table_list
*
next_independent
()
{
if
(
view
)
return
old_next
;
return
next_global
;
}
}
TABLE_LIST
;
class
Item
;
...
...
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