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;
...
@@ -1633,3 +1633,16 @@ use mysqltest;
create view v1 as select * from t1;
create view v1 as select * from t1;
revoke all privileges on mysqltest.* from mysqltest_1@localhost;
revoke all privileges on mysqltest.* from mysqltest_1@localhost;
drop database mysqltest;
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;
...
@@ -1568,7 +1568,23 @@ connection user1;
use
mysqltest
;
use
mysqltest
;
create
view
v1
as
select
*
from
t1
;
create
view
v1
as
select
*
from
t1
;
connection
root
;
connection
root
;
revoke
all
privileges
on
mysqltest
.*
from
mysqltest_1
@
localhost
;
revoke
all
privileges
on
mysqltest
.*
from
mysqltest_1
@
localhost
;
drop
database
mysqltest
;
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)
...
@@ -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
,
void
fill_effective_table_privileges
(
THD
*
thd
,
GRANT_INFO
*
grant
,
const
char
*
db
,
const
char
*
table
)
const
char
*
db
,
const
char
*
table
)
{
{
/* --skip-grants */
if
(
!
initialized
)
{
grant
->
privilege
=
~
NO_ACCESS
;
// everything is allowed
return
;
}
/* global privileges */
/* global privileges */
grant
->
privilege
=
thd
->
master_access
;
grant
->
privilege
=
thd
->
master_access
;
/* db privileges */
/* db privileges */
grant
->
privilege
|=
acl_get
(
thd
->
host
,
thd
->
ip
,
thd
->
priv_user
,
db
,
0
);
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
)
if
(
!
grant_option
)
return
;
return
;
...
...
sql/sql_base.cc
View file @
3d389a03
...
@@ -593,7 +593,8 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table,
...
@@ -593,7 +593,8 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table,
{
{
if
((
!
strcmp
(
table
->
db
,
db_name
)
&&
if
((
!
strcmp
(
table
->
db
,
db_name
)
&&
!
strcmp
(
table
->
real_name
,
table_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_cache_key
,
db_name
)
&&
!
strcmp
(
table
->
table
->
table_name
,
table_name
)))
!
strcmp
(
table
->
table
->
table_name
,
table_name
)))
break
;
break
;
...
@@ -618,6 +619,8 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table,
...
@@ -618,6 +619,8 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table,
TABLE_LIST
*
unique_table
(
TABLE_LIST
*
table
,
TABLE_LIST
*
table_list
)
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
;
TABLE_LIST
*
res
;
const
char
*
d_name
=
table
->
db
,
*
t_name
=
table
->
real_name
;
const
char
*
d_name
=
table
->
db
,
*
t_name
=
table
->
real_name
;
char
d_name_buff
[
MAX_ALIAS_NAME
],
t_name_buff
[
MAX_ALIAS_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)
...
@@ -644,13 +647,18 @@ TABLE_LIST* unique_table(TABLE_LIST *table, TABLE_LIST *table_list)
return
0
;
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.
if
(
!
(
res
=
find_table_in_global_list
(
table_list
,
d_name
,
t_name
))
||
return
find_table_in_global_list
(
res
->
next_global
,
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)
...
@@ -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"
);
my_error
(
ER_NON_UPDATABLE_TABLE
,
MYF
(
0
),
table_list
->
alias
,
"DELETE"
);
DBUG_RETURN
(
-
1
);
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
);
my_error
(
ER_UPDATE_TABLE_USED
,
MYF
(
0
),
table_list
->
real_name
);
DBUG_RETURN
(
-
1
);
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,
...
@@ -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
))))
setup_fields
(
thd
,
0
,
table_list
,
update_values
,
0
,
0
,
0
))))
DBUG_RETURN
(
-
1
);
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
);
my_error
(
ER_UPDATE_TABLE_USED
,
MYF
(
0
),
table_list
->
real_name
);
DBUG_RETURN
(
-
1
);
DBUG_RETURN
(
-
1
);
...
...
sql/sql_parse.cc
View file @
3d389a03
...
@@ -2810,7 +2810,7 @@ mysql_execute_command(THD *thd)
...
@@ -2810,7 +2810,7 @@ mysql_execute_command(THD *thd)
Is table which we are changing used somewhere in other parts of
Is table which we are changing used somewhere in other parts of
query
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 */
/* Using same table for INSERT and SELECT */
select_lex
->
options
|=
OPTION_BUFFER_RESULT
;
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,
...
@@ -529,7 +529,7 @@ int mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
DBUG_RETURN
(
-
1
);
DBUG_RETURN
(
-
1
);
/* Check that we are not using table that we are updating in a sub select */
/* 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
);
my_error
(
ER_UPDATE_TABLE_USED
,
MYF
(
0
),
table_list
->
real_name
);
DBUG_RETURN
(
-
1
);
DBUG_RETURN
(
-
1
);
...
...
sql/sql_view.cc
View file @
3d389a03
...
@@ -382,6 +382,7 @@ static LEX_STRING view_file_type[]= {{(char*)"VIEW", 4}};
...
@@ -382,6 +382,7 @@ static LEX_STRING view_file_type[]= {{(char*)"VIEW", 4}};
static
int
mysql_register_view
(
THD
*
thd
,
TABLE_LIST
*
view
,
static
int
mysql_register_view
(
THD
*
thd
,
TABLE_LIST
*
view
,
enum_view_create_mode
mode
)
enum_view_create_mode
mode
)
{
{
LEX
*
lex
=
thd
->
lex
;
char
buff
[
4096
];
char
buff
[
4096
];
String
str
(
buff
,(
uint32
)
sizeof
(
buff
),
system_charset_info
);
String
str
(
buff
,(
uint32
)
sizeof
(
buff
),
system_charset_info
);
char
md5
[
33
];
char
md5
[
33
];
...
@@ -395,7 +396,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
...
@@ -395,7 +396,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
{
{
ulong
sql_mode
=
thd
->
variables
.
sql_mode
&
MODE_ANSI_QUOTES
;
ulong
sql_mode
=
thd
->
variables
.
sql_mode
&
MODE_ANSI_QUOTES
;
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
;
thd
->
variables
.
sql_mode
|=
sql_mode
;
}
}
str
.
append
(
'\0'
);
str
.
append
(
'\0'
);
...
@@ -474,21 +475,21 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
...
@@ -474,21 +475,21 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
view
->
calc_md5
(
md5
);
view
->
calc_md5
(
md5
);
view
->
md5
.
str
=
md5
;
view
->
md5
.
str
=
md5
;
view
->
md5
.
length
=
32
;
view
->
md5
.
length
=
32
;
can_be_merged
=
thd
->
lex
->
can_be_merged
();
can_be_merged
=
lex
->
can_be_merged
();
if
(
thd
->
lex
->
create_view_algorithm
==
VIEW_ALGORITHM_MERGE
&&
if
(
lex
->
create_view_algorithm
==
VIEW_ALGORITHM_MERGE
&&
!
thd
->
lex
->
can_be_merged
())
!
lex
->
can_be_merged
())
{
{
push_warning
(
thd
,
MYSQL_ERROR
::
WARN_LEVEL_WARN
,
ER_WARN_VIEW_MERGE
,
push_warning
(
thd
,
MYSQL_ERROR
::
WARN_LEVEL_WARN
,
ER_WARN_VIEW_MERGE
,
ER
(
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
->
algorithm
=
lex
->
create_view_algorithm
;
view
->
with_check
=
thd
->
lex
->
create_view_check
;
view
->
with_check
=
lex
->
create_view_check
;
if
((
view
->
updatable_view
=
(
can_be_merged
&&
if
((
view
->
updatable_view
=
(
can_be_merged
&&
view
->
algorithm
!=
VIEW_ALGORITHM_TMPTABLE
)))
view
->
algorithm
!=
VIEW_ALGORITHM_TMPTABLE
)))
{
{
/* TODO: change here when we will support UNIONs */
/* 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
=
tbl
->
next_local
)
tbl
=
tbl
->
next_local
)
{
{
...
@@ -500,6 +501,26 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
...
@@ -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
&&
if
(
view
->
with_check
!=
VIEW_CHECK_NONE
&&
!
view
->
updatable_view
)
!
view
->
updatable_view
)
{
{
...
@@ -698,13 +719,12 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
...
@@ -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
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 is unique. Also we store old next table for the same purpose.
*/
*/
table
->
old_next
=
table
->
next_global
;
if
(
view_tables
)
if
(
view_tables
)
{
{
if
(
table
->
next_global
)
if
(
table
->
next_global
)
{
{
view_tables_tail
->
next_global
=
table
->
next_global
;
table
->
next_global
->
prev_global
=
&
view_tables_tail
->
next_global
;
table
->
next_global
->
prev_global
=
&
view_tables_tail
->
next_global
;
view_tables_tail
->
next_global
=
table
->
old_next
;
}
}
else
else
{
{
...
...
sql/table.h
View file @
3d389a03
...
@@ -232,8 +232,6 @@ typedef struct st_table_list
...
@@ -232,8 +232,6 @@ typedef struct st_table_list
st_table_list
*
ancestor
;
st_table_list
*
ancestor
;
/* most upper view this table belongs to */
/* most upper view this table belongs to */
st_table_list
*
belong_to_view
;
st_table_list
*
belong_to_view
;
/* next_global before adding VIEW tables */
st_table_list
*
old_next
;
Item
*
where
;
/* VIEW WHERE clause condition */
Item
*
where
;
/* VIEW WHERE clause condition */
Item
*
check_option
;
/* WITH CHECK OPTION condition */
Item
*
check_option
;
/* WITH CHECK OPTION condition */
LEX_STRING
query
;
/* text of (CRETE/SELECT) statement */
LEX_STRING
query
;
/* text of (CRETE/SELECT) statement */
...
@@ -286,12 +284,6 @@ typedef struct st_table_list
...
@@ -286,12 +284,6 @@ typedef struct st_table_list
bool
setup_ancestor
(
THD
*
thd
,
Item
**
conds
,
uint8
check_option
);
bool
setup_ancestor
(
THD
*
thd
,
Item
**
conds
,
uint8
check_option
);
bool
placeholder
()
{
return
derived
||
view
;
}
bool
placeholder
()
{
return
derived
||
view
;
}
void
print
(
THD
*
thd
,
String
*
str
);
void
print
(
THD
*
thd
,
String
*
str
);
inline
st_table_list
*
next_independent
()
{
if
(
view
)
return
old_next
;
return
next_global
;
}
}
TABLE_LIST
;
}
TABLE_LIST
;
class
Item
;
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