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
7c80937d
Commit
7c80937d
authored
Nov 08, 2004
by
bell@sanja.is.com.ua
Browse files
Options
Browse Files
Download
Plain Diff
Merge sanja.is.com.ua:/home/bell/mysql/bk/mysql-5.0
into sanja.is.com.ua:/home/bell/mysql/bk/work-update-5.0
parents
3d59f12a
9d0bb742
Changes
18
Show whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
342 additions
and
155 deletions
+342
-155
mysql-test/r/lock_multi.result
mysql-test/r/lock_multi.result
+1
-1
mysql-test/r/multi_update.result
mysql-test/r/multi_update.result
+22
-1
mysql-test/r/view.result
mysql-test/r/view.result
+2
-4
mysql-test/t/multi_update.test
mysql-test/t/multi_update.test
+33
-3
mysql-test/t/view.test
mysql-test/t/view.test
+0
-4
sql/item.cc
sql/item.cc
+17
-0
sql/item.h
sql/item.h
+1
-0
sql/mysql_priv.h
sql/mysql_priv.h
+5
-2
sql/sql_base.cc
sql/sql_base.cc
+8
-5
sql/sql_class.h
sql/sql_class.h
+6
-2
sql/sql_derived.cc
sql/sql_derived.cc
+135
-101
sql/sql_lex.cc
sql/sql_lex.cc
+1
-0
sql/sql_load.cc
sql/sql_load.cc
+1
-1
sql/sql_parse.cc
sql/sql_parse.cc
+0
-1
sql/sql_prepare.cc
sql/sql_prepare.cc
+5
-1
sql/sql_update.cc
sql/sql_update.cc
+80
-29
sql/table.cc
sql/table.cc
+18
-0
sql/table.h
sql/table.h
+7
-0
No files found.
mysql-test/r/lock_multi.result
View file @
7c80937d
...
...
@@ -26,7 +26,7 @@ lock table t1 read;
update t1,t2 set c=a where b=d;
select c from t2;
c
1
2
drop table t1;
drop table t2;
create table t1 (a int);
...
...
mysql-test/r/multi_update.result
View file @
7c80937d
...
...
@@ -155,7 +155,6 @@ ERROR HY000: Table 't2' was locked with a READ lock and can't be updated
UPDATE t1,t2 SET t1.d=t2.d,t2.d=30 WHERE t1.n=t2.n;
ERROR HY000: Table 't2' was locked with a READ lock and can't be updated
UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n;
ERROR HY000: Table 't2' was locked with a READ lock and can't be updated
unlock tables;
LOCK TABLES t1 write, t2 write;
UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n;
...
...
@@ -461,6 +460,7 @@ drop table t1, t2, t3;
create table t1 (col1 int);
create table t2 (col1 int);
update t1,t2 set t1.col1 = (select max(col1) from t1) where t1.col1 = t2.col1;
ERROR HY000: You can't specify target table 't1' for update in FROM clause
delete t1 from t1,t2 where t1.col1 < (select max(col1) from t1) and t1.col1 = t2.col1;
ERROR HY000: You can't specify target table 't1' for update in FROM clause
drop table t1,t2;
...
...
@@ -490,3 +490,24 @@ insert into t2 select * from t1;
delete t1,t2 from t2,t1 where t1.a<'B' and t2.b=t1.b;
set @@storage_engine=@ttype_save;
drop table t1,t2;
create table t1 (a int, b int);
insert into t1 values (1, 2), (2, 3), (3, 4);
create table t2 (a int);
insert into t2 values (10), (20), (30);
create view v1 as select a as b, a/10 as a from t2;
lock table t1 write;
alter table t1 add column c int default 100 after a;
update t1, v1 set t1.b=t1.a+t1.b+v1.b where t1.a=v1.a;
unlock tables;
select * from t1;
a c b
1 100 13
2 100 25
3 100 37
select * from t2;
a
10
20
30
drop view v1;
drop table t1, t2;
mysql-test/r/view.result
View file @
7c80937d
...
...
@@ -1339,16 +1339,14 @@ c
prepare stmt1 from "update v1,t1 set v1.s1=? where t1.s1=v1.s1";
set @arg='d';
execute stmt1 using @arg;
ERROR HY000: Table 't1' is read only
select * from v1;
s1
c
d
set @arg='e';
execute stmt1 using @arg;
ERROR HY000: Table 't1' is read only
select * from v1;
s1
c
e
deallocate prepare stmt1;
drop view v1;
drop table t1;
...
...
mysql-test/t/multi_update.test
View file @
7c80937d
...
...
@@ -159,8 +159,6 @@ LOCK TABLES t1 write, t2 read;
DELETE
t1
.*
,
t2
.*
FROM
t1
,
t2
where
t1
.
n
=
t2
.
n
;
--
error
1099
UPDATE
t1
,
t2
SET
t1
.
d
=
t2
.
d
,
t2
.
d
=
30
WHERE
t1
.
n
=
t2
.
n
;
--
QQ
This
should
not
generate
an
error
--
error
1099
UPDATE
t1
,
t2
SET
t1
.
d
=
t2
.
d
WHERE
t1
.
n
=
t2
.
n
;
unlock
tables
;
LOCK
TABLES
t1
write
,
t2
write
;
...
...
@@ -428,7 +426,7 @@ drop table t1, t2, t3;
#
create
table
t1
(
col1
int
);
create
table
t2
(
col1
int
);
--
QQ
The
following
should
give
error
1093
--
error
1093
update
t1
,
t2
set
t1
.
col1
=
(
select
max
(
col1
)
from
t1
)
where
t1
.
col1
=
t2
.
col1
;
--
error
1093
delete
t1
from
t1
,
t2
where
t1
.
col1
<
(
select
max
(
col1
)
from
t1
)
and
t1
.
col1
=
t2
.
col1
;
...
...
@@ -479,3 +477,35 @@ delete t1,t2 from t2,t1 where t1.a<'B' and t2.b=t1.b;
set
@@
storage_engine
=@
ttype_save
;
drop
table
t1
,
t2
;
create
table
t1
(
a
int
,
b
int
);
insert
into
t1
values
(
1
,
2
),
(
2
,
3
),
(
3
,
4
);
create
table
t2
(
a
int
);
insert
into
t2
values
(
10
),
(
20
),
(
30
);
create
view
v1
as
select
a
as
b
,
a
/
10
as
a
from
t2
;
connect
(
locker
,
localhost
,
root
,,
test
);
connection
locker
;
lock
table
t1
write
;
connect
(
changer
,
localhost
,
root
,,
test
);
connection
changer
;
send
alter
table
t1
add
column
c
int
default
100
after
a
;
connect
(
updater
,
localhost
,
root
,,
test
);
connection
updater
;
send
update
t1
,
v1
set
t1
.
b
=
t1
.
a
+
t1
.
b
+
v1
.
b
where
t1
.
a
=
v1
.
a
;
connection
locker
;
sleep
2
;
unlock
tables
;
connection
changer
;
reap
;
connection
updater
;
reap
;
select
*
from
t1
;
select
*
from
t2
;
drop
view
v1
;
drop
table
t1
,
t2
;
mysql-test/t/view.test
View file @
7c80937d
...
...
@@ -1300,13 +1300,9 @@ update v1,t1 set v1.s1='c' where t1.s1=v1.s1;
select
*
from
v1
;
prepare
stmt1
from
"update v1,t1 set v1.s1=? where t1.s1=v1.s1"
;
set
@
arg
=
'd'
;
--
QQ
This
should
not
generate
an
error
--
error
1036
execute
stmt1
using
@
arg
;
select
*
from
v1
;
set
@
arg
=
'e'
;
--
QQ
This
should
not
generate
an
error
--
error
1036
execute
stmt1
using
@
arg
;
select
*
from
v1
;
deallocate
prepare
stmt1
;
...
...
sql/item.cc
View file @
7c80937d
...
...
@@ -117,6 +117,23 @@ void Item::cleanup()
DBUG_VOID_RETURN
;
}
/*
cleanup() item if it is 'fixed'
SYNOPSIS
cleanup_processor()
arg - a dummy parameter, is not used here
*/
bool
Item
::
cleanup_processor
(
byte
*
arg
)
{
if
(
fixed
)
cleanup
();
return
FALSE
;
}
Item_ident
::
Item_ident
(
const
char
*
db_name_par
,
const
char
*
table_name_par
,
const
char
*
field_name_par
)
:
orig_db_name
(
db_name_par
),
orig_table_name
(
table_name_par
),
...
...
sql/item.h
View file @
7c80937d
...
...
@@ -283,6 +283,7 @@ public:
virtual
bool
remove_dependence_processor
(
byte
*
arg
)
{
return
0
;
}
virtual
bool
remove_fixed
(
byte
*
arg
)
{
fixed
=
0
;
return
0
;
}
virtual
bool
cleanup_processor
(
byte
*
arg
);
virtual
bool
collect_item_field_processor
(
byte
*
arg
)
{
return
0
;
}
virtual
Item
*
equal_fields_propagator
(
byte
*
arg
)
{
return
this
;
}
virtual
Item
*
set_no_const_sub
(
byte
*
arg
)
{
return
this
;
}
...
...
sql/mysql_priv.h
View file @
7c80937d
...
...
@@ -565,7 +565,11 @@ int mysql_explain_select(THD *thd, SELECT_LEX *sl, char const *type,
select_result
*
result
);
int
mysql_union
(
THD
*
thd
,
LEX
*
lex
,
select_result
*
result
,
SELECT_LEX_UNIT
*
unit
);
int
mysql_handle_derived
(
LEX
*
lex
);
int
mysql_handle_derived
(
LEX
*
lex
,
int
(
*
processor
)(
THD
*
thd
,
st_lex
*
lex
,
st_table_list
*
table
));
int
mysql_derived_prepare
(
THD
*
thd
,
LEX
*
lex
,
TABLE_LIST
*
t
);
int
mysql_derived_filling
(
THD
*
thd
,
LEX
*
lex
,
TABLE_LIST
*
t
);
Field
*
create_tmp_field
(
THD
*
thd
,
TABLE
*
table
,
Item
*
item
,
Item
::
Type
type
,
Item
***
copy_func
,
Field
**
from_field
,
bool
group
,
bool
modify_item
,
uint
convert_blob_length
);
...
...
@@ -792,7 +796,6 @@ void wait_for_refresh(THD *thd);
int
open_tables
(
THD
*
thd
,
TABLE_LIST
*
tables
,
uint
*
counter
);
int
simple_open_n_lock_tables
(
THD
*
thd
,
TABLE_LIST
*
tables
);
int
open_and_lock_tables
(
THD
*
thd
,
TABLE_LIST
*
tables
);
void
relink_tables_for_derived
(
THD
*
thd
);
int
lock_tables
(
THD
*
thd
,
TABLE_LIST
*
tables
,
uint
counter
);
TABLE
*
open_temporary_table
(
THD
*
thd
,
const
char
*
path
,
const
char
*
db
,
const
char
*
table_name
,
bool
link_in_list
);
...
...
sql/sql_base.cc
View file @
7c80937d
...
...
@@ -44,6 +44,7 @@ static my_bool open_new_frm(const char *path, const char *alias,
uint
db_stat
,
uint
prgflag
,
uint
ha_open_flags
,
TABLE
*
outparam
,
TABLE_LIST
*
table_desc
,
MEM_ROOT
*
mem_root
);
static
void
relink_tables_for_multidelete
(
THD
*
thd
);
extern
"C"
byte
*
table_cache_key
(
const
byte
*
record
,
uint
*
length
,
my_bool
not_used
__attribute__
((
unused
)))
...
...
@@ -1859,19 +1860,21 @@ int open_and_lock_tables(THD *thd, TABLE_LIST *tables)
uint
counter
;
if
(
open_tables
(
thd
,
tables
,
&
counter
)
||
lock_tables
(
thd
,
tables
,
counter
)
||
mysql_handle_derived
(
thd
->
lex
))
mysql_handle_derived
(
thd
->
lex
,
&
mysql_derived_prepare
)
||
(
thd
->
fill_derived_tables
()
&&
mysql_handle_derived
(
thd
->
lex
,
&
mysql_derived_filling
)))
DBUG_RETURN
(
thd
->
net
.
report_error
?
-
1
:
1
);
/* purecov: inspected */
relink_tables_for_
derived
(
thd
);
relink_tables_for_
multidelete
(
thd
);
DBUG_RETURN
(
0
);
}
/*
Let us propagate pointers to open tables from global table list
to table lists
in particular selects if needed.
to table lists
for multi-delete
*/
void
relink_tables_for_derived
(
THD
*
thd
)
static
void
relink_tables_for_multidelete
(
THD
*
thd
)
{
if
(
thd
->
lex
->
all_selects_list
->
next_select_in_list
()
||
thd
->
lex
->
time_zone_tables_used
)
...
...
sql/sql_class.h
View file @
7c80937d
...
...
@@ -1131,6 +1131,10 @@ public:
{
return
command
==
COM_PREPARE
;
}
inline
bool
fill_derived_tables
()
{
return
!
only_prepare
()
&&
!
lex
->
only_view_structure
();
}
inline
gptr
trans_alloc
(
unsigned
int
size
)
{
return
alloc_root
(
&
transaction
.
mem_root
,
size
);
...
...
sql/sql_derived.cc
View file @
7c80937d
...
...
@@ -25,15 +25,15 @@
#include "sql_select.h"
#include "sql_acl.h"
static
int
mysql_derived
(
THD
*
thd
,
LEX
*
lex
,
SELECT_LEX_UNIT
*
s
,
TABLE_LIST
*
t
);
/*
Resolve derived tables in all queries
call given derived table processor (preparing or filling tables)
SYNOPSIS
mysql_handle_derived()
lex LEX for this thread
processor procedure of derived table processing
RETURN
0 ok
...
...
@@ -42,7 +42,7 @@ static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s,
*/
int
mysql_handle_derived
(
LEX
*
lex
)
mysql_handle_derived
(
LEX
*
lex
,
int
(
*
processor
)(
THD
*
,
LEX
*
,
TABLE_LIST
*
)
)
{
if
(
lex
->
derived_tables
)
{
...
...
@@ -55,15 +55,9 @@ mysql_handle_derived(LEX *lex)
cursor
=
cursor
->
next_local
)
{
int
res
;
if
(
cursor
->
derived
&&
(
res
=
mysql_derived
(
lex
->
thd
,
lex
,
cursor
->
derived
,
cursor
)))
{
if
((
res
=
(
*
processor
)(
lex
->
thd
,
lex
,
cursor
)))
return
res
;
}
else
if
(
cursor
->
ancestor
)
cursor
->
set_ancestor
();
}
if
(
lex
->
describe
)
{
/*
...
...
@@ -80,20 +74,16 @@ mysql_handle_derived(LEX *lex)
/*
Resolve derived tables in all queries
Create temporary table structure (but do not fill it)
SYNOPSIS
mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
thd Thread handle
lex LEX for this thread
unit node that contains all SELECT's for derived tables
t TABLE_LIST for the upper SELECT
orig_table_list TABLE_LIST for the upper SELECT
IMPLEMENTATION
Derived table is resolved with temporary table. It is created based on the
queries defined. After temporary table is created, if this is not EXPLAIN,
then the entire unit / node is deleted. unit is deleted if UNION is used
for derived table and node is deleted is it is a simple SELECT.
Derived table is resolved with temporary table.
After table creation, the above TABLE_LIST is updated with a new table.
...
...
@@ -107,19 +97,19 @@ mysql_handle_derived(LEX *lex)
0 ok
1 Error
-1 Error and error message given
*/
*/
static
int
mysql_derived
(
THD
*
thd
,
LEX
*
lex
,
SELECT_LEX_UNIT
*
unit
,
TABLE_LIST
*
org_table_list
)
int
mysql_derived_prepare
(
THD
*
thd
,
LEX
*
lex
,
TABLE_LIST
*
orig_table_list
)
{
SELECT_LEX_UNIT
*
unit
=
orig_table_list
->
derived
;
int
res
=
0
;
if
(
unit
)
{
SELECT_LEX
*
first_select
=
unit
->
first_select
();
TABLE
*
table
;
int
res
;
TABLE
*
table
=
0
;
select_union
*
derived_result
;
bool
is_union
=
first_select
->
next_select
()
&&
first_select
->
next_select
()
->
linkage
==
UNION_TYPE
;
SELECT_LEX
*
save_current_select
=
lex
->
current_select
;
DBUG_ENTER
(
"mysql_derived"
);
if
(
!
(
derived_result
=
new
select_union
(
0
)))
...
...
@@ -142,24 +132,90 @@ static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
(
first_select
->
options
|
thd
->
options
|
TMP_TABLE_ALL_COLUMNS
),
HA_POS_ERROR
,
or
g_table_list
->
alias
)))
ori
g_table_list
->
alias
)))
{
res
=
-
1
;
goto
exit
;
}
derived_result
->
set_table
(
table
);
exit:
/*
if it is preparation PS only or commands that need only VIEW structure
then we do not need real data and we can skip execution (and parameters
is not defined, too)
*/
if
(
!
thd
->
only_prepare
()
&&
!
lex
->
only_view_structure
()
)
if
(
res
)
{
if
(
table
)
free_tmp_table
(
thd
,
table
);
delete
derived_result
;
}
else
{
if
(
!
thd
->
fill_derived_tables
())
delete
derived_result
;
orig_table_list
->
derived_result
=
derived_result
;
orig_table_list
->
table
=
table
;
orig_table_list
->
real_name
=
table
->
real_name
;
table
->
derived_select_number
=
first_select
->
select_number
;
table
->
tmp_table
=
TMP_TABLE
;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
table
->
grant
.
privilege
=
SELECT_ACL
;
#endif
orig_table_list
->
db
=
(
char
*
)
""
;
// Force read of table stats in the optimizer
table
->
file
->
info
(
HA_STATUS_VARIABLE
);
/* Add new temporary table to list of open derived tables */
table
->
next
=
thd
->
derived_tables
;
thd
->
derived_tables
=
table
;
}
}
else
if
(
orig_table_list
->
ancestor
)
orig_table_list
->
set_ancestor
();
return
(
res
);
}
/*
fill derived table
SYNOPSIS
mysql_derived_filling()
thd Thread handle
lex LEX for this thread
unit node that contains all SELECT's for derived tables
orig_table_list TABLE_LIST for the upper SELECT
IMPLEMENTATION
Derived table is resolved with temporary table. It is created based on the
queries defined. After temporary table is filled, if this is not EXPLAIN,
then the entire unit / node is deleted. unit is deleted if UNION is used
for derived table and node is deleted is it is a simple SELECT.
RETURN
0 ok
1 Error
-1 Error and error message given
*/
int
mysql_derived_filling
(
THD
*
thd
,
LEX
*
lex
,
TABLE_LIST
*
orig_table_list
)
{
TABLE
*
table
=
orig_table_list
->
table
;
SELECT_LEX_UNIT
*
unit
=
orig_table_list
->
derived
;
int
res
=
0
;
/*check that table creation pass without problem and it is derived table */
if
(
table
&&
unit
)
{
SELECT_LEX
*
first_select
=
unit
->
first_select
();
select_union
*
derived_result
=
orig_table_list
->
derived_result
;
SELECT_LEX
*
save_current_select
=
lex
->
current_select
;
bool
is_union
=
first_select
->
next_select
()
&&
first_select
->
next_select
()
->
linkage
==
UNION_TYPE
;
if
(
is_union
)
{
// execute union without clean up
if
(
!
(
res
=
unit
->
prepare
(
thd
,
derived_result
,
SELECT_NO_UNLOCK
)))
res
=
unit
->
exec
();
}
else
...
...
@@ -186,7 +242,6 @@ static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
SELECT_NO_UNLOCK
),
derived_result
,
unit
,
first_select
);
}
}
if
(
!
res
)
{
...
...
@@ -196,39 +251,18 @@ static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
*/
if
(
derived_result
->
flush
())
res
=
1
;
else
{
org_table_list
->
real_name
=
table
->
real_name
;
org_table_list
->
table
=
table
;
table
->
derived_select_number
=
first_select
->
select_number
;
table
->
tmp_table
=
TMP_TABLE
;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
table
->
grant
.
privilege
=
SELECT_ACL
;
#endif
org_table_list
->
db
=
(
char
*
)
""
;
// Force read of table stats in the optimizer
table
->
file
->
info
(
HA_STATUS_VARIABLE
);
}
if
(
!
lex
->
describe
)
unit
->
cleanup
();
if
(
res
)
free_tmp_table
(
thd
,
table
);
else
{
/* Add new temporary table to list of open derived tables */
table
->
next
=
thd
->
derived_tables
;
thd
->
derived_tables
=
table
;
}
}
else
{
free_tmp_table
(
thd
,
table
);
unit
->
cleanup
();
}
exit:
delete
derived_result
;
lex
->
current_select
=
save_current_select
;
DBUG_RETURN
(
res
);
if
(
res
)
free_tmp_table
(
thd
,
table
);
}
return
res
;
}
sql/sql_lex.cc
View file @
7c80937d
...
...
@@ -176,6 +176,7 @@ void lex_start(THD *thd, uchar *buf,uint length)
lex
->
sphead
=
NULL
;
lex
->
spcont
=
NULL
;
lex
->
trg_table
=
NULL
;
lex
->
proc_list
.
first
=
0
;
extern
byte
*
sp_lex_spfuns_key
(
const
byte
*
ptr
,
uint
*
plen
,
my_bool
first
);
hash_free
(
&
lex
->
spfuns
);
...
...
sql/sql_load.cc
View file @
7c80937d
...
...
@@ -91,7 +91,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
int
error
;
String
*
field_term
=
ex
->
field_term
,
*
escaped
=
ex
->
escaped
;
String
*
enclosed
=
ex
->
enclosed
;
Item
*
unused_conds
;
Item
*
unused_conds
=
0
;
bool
is_fifo
=
0
;
#ifndef EMBEDDED_LIBRARY
LOAD_FILE_INFO
lf_info
;
...
...
sql/sql_parse.cc
View file @
7c80937d
...
...
@@ -4472,7 +4472,6 @@ mysql_init_select(LEX *lex)
{
DBUG_ASSERT
(
lex
->
result
==
0
);
lex
->
exchange
=
0
;
lex
->
proc_list
.
first
=
0
;
}
}
...
...
sql/sql_prepare.cc
View file @
7c80937d
...
...
@@ -1315,7 +1315,11 @@ static int mysql_test_multiupdate(Prepared_statement *stmt,
int
res
;
if
((
res
=
multi_update_precheck
(
stmt
->
thd
,
tables
)))
return
res
;
return
select_like_statement_test
(
stmt
,
tables
,
&
mysql_multi_update_prepare
);
/*
here we do not pass tables for opening, tables will be opened and locked
by mysql_multi_update_prepare
*/
return
select_like_statement_test
(
stmt
,
0
,
&
mysql_multi_update_prepare
);
}
...
...
sql/sql_update.cc
View file @
7c80937d
...
...
@@ -575,13 +575,21 @@ static table_map get_table_map(List<Item> *items)
int
mysql_multi_update_prepare
(
THD
*
thd
)
{
LEX
*
lex
=
thd
->
lex
;
ulong
opened_tables
;
TABLE_LIST
*
table_list
=
lex
->
query_tables
;
List
<
Item
>
*
fields
=
&
lex
->
select_lex
.
item_list
;
TABLE_LIST
*
tl
;
table_map
tables_for_update
=
0
,
readonly_tables
=
0
;
table_map
tables_for_update
;
int
res
;
bool
update_view
=
0
;
uint
table_count
;
const
bool
using_lock_tables
=
thd
->
locked_tables
!=
0
;
DBUG_ENTER
(
"mysql_multi_update_prepare"
);
/* open tables and create derived ones, but do not lock and fill them */
if
(
open_tables
(
thd
,
table_list
,
&
table_count
)
||
mysql_handle_derived
(
lex
,
&
mysql_derived_prepare
))
DBUG_RETURN
(
thd
->
net
.
report_error
?
-
1
:
1
);
/*
Ensure that we have update privilege for all tables and columns in the
SET part
...
...
@@ -606,9 +614,9 @@ int mysql_multi_update_prepare(THD *thd)
call in setup_tables()).
*/
if
(
setup_tables
(
thd
,
table_list
,
&
lex
->
select_lex
.
where
)
||
(
thd
->
lex
->
select_lex
.
no_wrap_view_item
=
1
,
(
lex
->
select_lex
.
no_wrap_view_item
=
1
,
res
=
setup_fields
(
thd
,
0
,
table_list
,
*
fields
,
1
,
0
,
0
),
thd
->
lex
->
select_lex
.
no_wrap_view_item
=
0
,
lex
->
select_lex
.
no_wrap_view_item
=
0
,
res
))
DBUG_RETURN
(
-
1
);
...
...
@@ -626,18 +634,10 @@ int mysql_multi_update_prepare(THD *thd)
DBUG_RETURN
(
-
1
);
}
{
// Find tables used in items
List_iterator_fast
<
Item
>
it
(
*
fields
);
Item
*
item
;
while
((
item
=
it
++
))
{
tables_for_update
|=
item
->
used_tables
();
}
}
tables_for_update
=
get_table_map
(
fields
);
/*
Count tables and setup timestamp handling
Setup timestamp handling and locking mode
*/
for
(
tl
=
table_list
;
tl
;
tl
=
tl
->
next_local
)
{
...
...
@@ -651,22 +651,78 @@ int mysql_multi_update_prepare(THD *thd)
table
->
timestamp_field
->
query_id
==
thd
->
query_id
)
table
->
timestamp_field_type
=
TIMESTAMP_NO_AUTO_SET
;
if
(
!
tl
->
updatable
||
check_key_in_view
(
thd
,
tl
))
readonly_tables
|=
table
->
map
;
}
if
(
tables_for_update
&
readonly_tables
)
{
// find readonly table/view which cause error
for
(
tl
=
table_list
;
tl
;
tl
=
tl
->
next_local
)
/* if table will be updated then check that it is unique */
if
(
table
->
map
&
tables_for_update
)
{
if
((
readonly_tables
&
tl
->
table
->
map
)
&&
(
tables_for_update
&
tl
->
table
->
map
))
if
(
!
tl
->
updatable
||
check_key_in_view
(
thd
,
tl
))
{
my_error
(
ER_NON_UPDATABLE_TABLE
,
MYF
(
0
),
tl
->
alias
,
"UPDATE"
);
DBUG_RETURN
(
-
1
);
}
/*
Multi-update can't be constructed over-union => we always have
single SELECT on top and have to check underlaying SELECTs of it
*/
if
(
lex
->
select_lex
.
check_updateable_in_subqueries
(
tl
->
db
,
tl
->
real_name
))
{
my_error
(
ER_UPDATE_TABLE_USED
,
MYF
(
0
),
tl
->
real_name
);
DBUG_RETURN
(
-
1
);
}
DBUG_PRINT
(
"info"
,(
"setting table `%s` for update"
,
tl
->
alias
));
tl
->
lock_type
=
lex
->
multi_lock_option
;
tl
->
updating
=
1
;
}
else
{
DBUG_PRINT
(
"info"
,(
"setting table `%s` for read-only"
,
tl
->
alias
));
tl
->
lock_type
=
TL_READ
;
tl
->
updating
=
0
;
}
if
(
!
using_lock_tables
)
tl
->
table
->
reginfo
.
lock_type
=
tl
->
lock_type
;
}
opened_tables
=
thd
->
status_var
.
opened_tables
;
/* now lock and fill tables */
if
(
lock_tables
(
thd
,
table_list
,
table_count
))
DBUG_RETURN
(
thd
->
net
.
report_error
?
-
1
:
1
);
/*
we have to re-call fixfields for fixed items, because lock maybe
reopened tables
*/
if
(
opened_tables
!=
thd
->
status_var
.
opened_tables
)
{
/*
Fields items cleanup(). There are only Item_fields in the list, so we
do not do Item tree walking
*/
List_iterator_fast
<
Item
>
it
(
*
fields
);
Item
*
item
;
while
(
item
=
it
++
)
{
item
->
cleanup
();
}
/* We have to cleunup translation tables of views. */
for
(
TABLE_LIST
*
tbl
=
table_list
;
tbl
;
tbl
=
tbl
->
next_global
)
tbl
->
cleanup_items
();
/* undone setup_tables() */
table_list
->
setup_is_done
=
0
;
if
(
setup_tables
(
thd
,
table_list
,
&
lex
->
select_lex
.
where
)
||
(
lex
->
select_lex
.
no_wrap_view_item
=
1
,
res
=
setup_fields
(
thd
,
0
,
table_list
,
*
fields
,
1
,
0
,
0
),
lex
->
select_lex
.
no_wrap_view_item
=
0
,
res
))
DBUG_RETURN
(
-
1
);
}
if
(
thd
->
fill_derived_tables
()
&&
mysql_handle_derived
(
lex
,
&
mysql_derived_filling
))
DBUG_RETURN
(
thd
->
net
.
report_error
?
-
1
:
1
);
DBUG_RETURN
(
0
);
}
...
...
@@ -688,11 +744,6 @@ int mysql_multi_update(THD *thd,
multi_update
*
result
;
DBUG_ENTER
(
"mysql_multi_update"
);
/* QQ: This should be fixed soon to get lower granularity locks */
select_lex
->
set_lock_for_tables
(
thd
->
lex
->
multi_lock_option
);
if
((
res
=
open_and_lock_tables
(
thd
,
table_list
)))
DBUG_RETURN
(
res
);
if
((
res
=
mysql_multi_update_prepare
(
thd
)))
DBUG_RETURN
(
res
);
...
...
sql/table.cc
View file @
7c80937d
...
...
@@ -1735,6 +1735,24 @@ err:
}
/*
cleunup items belonged to view fields translation table
SYNOPSIS
st_table_list::cleanup_items()
*/
void
st_table_list
::
cleanup_items
()
{
if
(
!
field_translation
)
return
;
Item
**
end
=
field_translation
+
view
->
select_lex
.
item_list
.
elements
;
for
(
Item
**
item
=
field_translation
;
item
<
end
;
item
++
)
(
*
item
)
->
walk
(
&
Item
::
cleanup_processor
,
0
);
}
/*
check CHECK OPTION condition
...
...
sql/table.h
View file @
7c80937d
...
...
@@ -222,6 +222,7 @@ struct st_table {
#define VIEW_CHECK_SKIP 2
struct
st_lex
;
struct
select_union
;
typedef
struct
st_table_list
{
...
...
@@ -237,6 +238,11 @@ typedef struct st_table_list
/* ... join ... USE INDEX ... IGNORE INDEX */
List
<
String
>
*
use_index
,
*
ignore_index
;
TABLE
*
table
;
/* opened table */
/*
select_result for derived table to pass it from table creation to table
filling procedure
*/
select_union
*
derived_result
;
/*
Reference from aux_tables to local list entry of main select of
multi-delete statement:
...
...
@@ -306,6 +312,7 @@ typedef struct st_table_list
void
set_ancestor
();
int
view_check_option
(
THD
*
thd
,
bool
ignore_failure
);
bool
setup_ancestor
(
THD
*
thd
,
Item
**
conds
,
uint8
check_option
);
void
cleanup_items
();
bool
placeholder
()
{
return
derived
||
view
;
}
void
print
(
THD
*
thd
,
String
*
str
);
inline
st_table_list
*
next_independent
()
...
...
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