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
1bf318b8
Commit
1bf318b8
authored
Jul 31, 2007
by
kostja@bodhi.(none)
Browse files
Options
Browse Files
Download
Plain Diff
Merge bk-internal.mysql.com:/home/bk/mysql-5.0
into bodhi.(none):/opt/local/work/mysql-5.0-runtime
parents
81905ee1
80b48aea
Changes
22
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
711 additions
and
165 deletions
+711
-165
client/mysqldump.c
client/mysqldump.c
+27
-3
mysql-test/r/innodb_mysql.result
mysql-test/r/innodb_mysql.result
+28
-0
mysql-test/r/mysqldump-max.result
mysql-test/r/mysqldump-max.result
+36
-0
mysql-test/r/mysqldump.result
mysql-test/r/mysqldump.result
+180
-0
mysql-test/r/openssl_1.result
mysql-test/r/openssl_1.result
+9
-0
mysql-test/r/show_check.result
mysql-test/r/show_check.result
+20
-0
mysql-test/r/sp-prelocking.result
mysql-test/r/sp-prelocking.result
+30
-0
mysql-test/t/innodb_mysql.test
mysql-test/t/innodb_mysql.test
+33
-0
mysql-test/t/show_check.test
mysql-test/t/show_check.test
+57
-0
mysql-test/t/sp-prelocking.test
mysql-test/t/sp-prelocking.test
+31
-0
sql/handler.h
sql/handler.h
+36
-3
sql/lock.cc
sql/lock.cc
+29
-6
sql/mysql_priv.h
sql/mysql_priv.h
+2
-1
sql/opt_range.cc
sql/opt_range.cc
+3
-3
sql/sp.cc
sql/sp.cc
+2
-2
sql/sql_base.cc
sql/sql_base.cc
+36
-4
sql/sql_class.h
sql/sql_class.h
+18
-6
sql/sql_lex.cc
sql/sql_lex.cc
+130
-3
sql/sql_table.cc
sql/sql_table.cc
+3
-3
sql/sql_yacc.yy
sql/sql_yacc.yy
+1
-1
sql/table.cc
sql/table.cc
+0
-129
sql/table.h
sql/table.h
+0
-1
No files found.
client/mysqldump.c
View file @
1bf318b8
...
...
@@ -992,6 +992,21 @@ static int mysql_query_with_error_report(MYSQL *mysql_con, MYSQL_RES **res,
return
0
;
}
static
int
switch_character_set_results
(
MYSQL
*
mysql
,
const
char
*
cs_name
)
{
char
query_buffer
[
QUERY_LENGTH
];
size_t
query_length
;
query_length
=
my_snprintf
(
query_buffer
,
sizeof
(
query_buffer
),
"SET SESSION character_set_results = '%s'"
,
(
const
char
*
)
cs_name
);
return
mysql_real_query
(
mysql
,
query_buffer
,
query_length
);
}
/*
Open a new .sql file to dump the table or view into
...
...
@@ -1671,7 +1686,10 @@ static uint get_table_structure(char *table, char *db, char *table_type,
MYSQL_FIELD
*
field
;
my_snprintf
(
buff
,
sizeof
(
buff
),
"show create table %s"
,
result_table
);
if
(
mysql_query_with_error_report
(
mysql
,
0
,
buff
))
if
(
switch_character_set_results
(
mysql
,
"binary"
)
||
mysql_query_with_error_report
(
mysql
,
&
result
,
buff
)
||
switch_character_set_results
(
mysql
,
default_charset
))
DBUG_RETURN
(
0
);
if
(
path
)
...
...
@@ -1702,7 +1720,6 @@ static uint get_table_structure(char *table, char *db, char *table_type,
check_io
(
sql_file
);
}
result
=
mysql_store_result
(
mysql
);
field
=
mysql_fetch_field_direct
(
result
,
0
);
if
(
strcmp
(
field
->
name
,
"View"
)
==
0
)
{
...
...
@@ -1794,7 +1811,14 @@ static uint get_table_structure(char *table, char *db, char *table_type,
}
row
=
mysql_fetch_row
(
result
);
fprintf
(
sql_file
,
"%s;
\n
"
,
row
[
1
]);
fprintf
(
sql_file
,
"SET @saved_cs_client = @@character_set_client;
\n
"
"SET character_set_client = utf8;
\n
"
"%s;
\n
"
"SET character_set_client = @saved_cs_client;
\n
"
,
row
[
1
]);
check_io
(
sql_file
);
mysql_free_result
(
result
);
}
...
...
mysql-test/r/innodb_mysql.result
View file @
1bf318b8
...
...
@@ -739,6 +739,34 @@ drop table if exists t1;
create table t1 (a int) engine=innodb;
alter table t1 alter a set default 1;
drop table t1;
Bug#24918 drop table and lock / inconsistent between
perm and temp tables
Check transactional tables under LOCK TABLES
drop table if exists t24918, t24918_tmp, t24918_trans, t24918_trans_tmp,
t24918_access;
create table t24918_access (id int);
create table t24918 (id int) engine=myisam;
create temporary table t24918_tmp (id int) engine=myisam;
create table t24918_trans (id int) engine=innodb;
create temporary table t24918_trans_tmp (id int) engine=innodb;
lock table t24918 write, t24918_tmp write, t24918_trans write, t24918_trans_tmp write;
drop table t24918;
select * from t24918_access;
ERROR HY000: Table 't24918_access' was not locked with LOCK TABLES
drop table t24918_trans;
select * from t24918_access;
ERROR HY000: Table 't24918_access' was not locked with LOCK TABLES
drop table t24918_trans_tmp;
select * from t24918_access;
ERROR HY000: Table 't24918_access' was not locked with LOCK TABLES
drop table t24918_tmp;
select * from t24918_access;
ERROR HY000: Table 't24918_access' was not locked with LOCK TABLES
unlock tables;
drop table t24918_access;
CREATE TABLE t1 (a int, b int, PRIMARY KEY (a), KEY bkey (b)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1,2),(3,2),(2,2),(4,2),(5,2),(6,2),(7,2),(8,2);
INSERT INTO t1 SELECT a + 8, 2 FROM t1;
...
...
mysql-test/r/mysqldump-max.result
View file @
1bf318b8
...
...
@@ -93,55 +93,73 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET l
USE `test`;
DROP TABLE IF EXISTS `t1`;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
CREATE TABLE `t1` (
`id` int(8) default NULL,
`name` varchar(32) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
SET character_set_client = @saved_cs_client;
/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
INSERT DELAYED IGNORE INTO `t1` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value');
/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
DROP TABLE IF EXISTS `t2`;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
CREATE TABLE `t2` (
`id` int(8) default NULL,
`name` varchar(32) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
SET character_set_client = @saved_cs_client;
/*!40000 ALTER TABLE `t2` DISABLE KEYS */;
INSERT DELAYED IGNORE INTO `t2` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value');
/*!40000 ALTER TABLE `t2` ENABLE KEYS */;
DROP TABLE IF EXISTS `t3`;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
CREATE TABLE `t3` (
`id` int(8) default NULL,
`name` varchar(32) default NULL
) ENGINE=MEMORY DEFAULT CHARSET=latin1;
SET character_set_client = @saved_cs_client;
/*!40000 ALTER TABLE `t3` DISABLE KEYS */;
INSERT DELAYED IGNORE INTO `t3` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value');
/*!40000 ALTER TABLE `t3` ENABLE KEYS */;
DROP TABLE IF EXISTS `t4`;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
CREATE TABLE `t4` (
`id` int(8) default NULL,
`name` varchar(32) default NULL
) ENGINE=MEMORY DEFAULT CHARSET=latin1;
SET character_set_client = @saved_cs_client;
/*!40000 ALTER TABLE `t4` DISABLE KEYS */;
INSERT DELAYED IGNORE INTO `t4` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value');
/*!40000 ALTER TABLE `t4` ENABLE KEYS */;
DROP TABLE IF EXISTS `t5`;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
CREATE TABLE `t5` (
`id` int(8) default NULL,
`name` varchar(32) default NULL
) ENGINE=ARCHIVE DEFAULT CHARSET=latin1;
SET character_set_client = @saved_cs_client;
/*!40000 ALTER TABLE `t5` DISABLE KEYS */;
INSERT DELAYED IGNORE INTO `t5` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value');
/*!40000 ALTER TABLE `t5` ENABLE KEYS */;
DROP TABLE IF EXISTS `t6`;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
CREATE TABLE `t6` (
`id` int(8) default NULL,
`name` varchar(32) default NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
SET character_set_client = @saved_cs_client;
/*!40000 ALTER TABLE `t6` DISABLE KEYS */;
INSERT IGNORE INTO `t6` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value');
...
...
@@ -172,55 +190,73 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET l
USE `test`;
DROP TABLE IF EXISTS `t1`;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
CREATE TABLE `t1` (
`id` int(8) default NULL,
`name` varchar(32) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
SET character_set_client = @saved_cs_client;
/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
INSERT DELAYED INTO `t1` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value');
/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
DROP TABLE IF EXISTS `t2`;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
CREATE TABLE `t2` (
`id` int(8) default NULL,
`name` varchar(32) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
SET character_set_client = @saved_cs_client;
/*!40000 ALTER TABLE `t2` DISABLE KEYS */;
INSERT DELAYED INTO `t2` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value');
/*!40000 ALTER TABLE `t2` ENABLE KEYS */;
DROP TABLE IF EXISTS `t3`;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
CREATE TABLE `t3` (
`id` int(8) default NULL,
`name` varchar(32) default NULL
) ENGINE=MEMORY DEFAULT CHARSET=latin1;
SET character_set_client = @saved_cs_client;
/*!40000 ALTER TABLE `t3` DISABLE KEYS */;
INSERT DELAYED INTO `t3` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value');
/*!40000 ALTER TABLE `t3` ENABLE KEYS */;
DROP TABLE IF EXISTS `t4`;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
CREATE TABLE `t4` (
`id` int(8) default NULL,
`name` varchar(32) default NULL
) ENGINE=MEMORY DEFAULT CHARSET=latin1;
SET character_set_client = @saved_cs_client;
/*!40000 ALTER TABLE `t4` DISABLE KEYS */;
INSERT DELAYED INTO `t4` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value');
/*!40000 ALTER TABLE `t4` ENABLE KEYS */;
DROP TABLE IF EXISTS `t5`;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
CREATE TABLE `t5` (
`id` int(8) default NULL,
`name` varchar(32) default NULL
) ENGINE=ARCHIVE DEFAULT CHARSET=latin1;
SET character_set_client = @saved_cs_client;
/*!40000 ALTER TABLE `t5` DISABLE KEYS */;
INSERT DELAYED INTO `t5` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value');
/*!40000 ALTER TABLE `t5` ENABLE KEYS */;
DROP TABLE IF EXISTS `t6`;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
CREATE TABLE `t6` (
`id` int(8) default NULL,
`name` varchar(32) default NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
SET character_set_client = @saved_cs_client;
/*!40000 ALTER TABLE `t6` DISABLE KEYS */;
INSERT INTO `t6` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value');
...
...
mysql-test/r/mysqldump.result
View file @
1bf318b8
This diff is collapsed.
Click to expand it.
mysql-test/r/openssl_1.result
View file @
1bf318b8
...
...
@@ -77,9 +77,12 @@ INSERT INTO t1 VALUES (1), (2);
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
DROP TABLE IF EXISTS `t1`;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
CREATE TABLE `t1` (
`a` int(11) default NULL
);
SET character_set_client = @saved_cs_client;
LOCK TABLES `t1` WRITE;
/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
...
...
@@ -108,9 +111,12 @@ UNLOCK TABLES;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
DROP TABLE IF EXISTS `t1`;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
CREATE TABLE `t1` (
`a` int(11) default NULL
);
SET character_set_client = @saved_cs_client;
LOCK TABLES `t1` WRITE;
/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
...
...
@@ -139,9 +145,12 @@ UNLOCK TABLES;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
DROP TABLE IF EXISTS `t1`;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
CREATE TABLE `t1` (
`a` int(11) default NULL
);
SET character_set_client = @saved_cs_client;
LOCK TABLES `t1` WRITE;
/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
...
...
mysql-test/r/show_check.result
View file @
1bf318b8
...
...
@@ -1088,6 +1088,26 @@ DROP TABLE t1;
DROP VIEW v1;
DROP PROCEDURE p1;
DROP FUNCTION f1;
set names koi8r;
DROP DATABASE IF EXISTS mysqltest1;
CREATE DATABASE mysqltest1;
use mysqltest1;
CREATE TABLE t1(1 INT);
---> Dumping mysqltest1 to show_check.mysqltest1.sql
DROP DATABASE mysqltest1;
---> Restoring mysqltest1...
SHOW CREATE TABLE mysqltest1.t1;
Table Create Table
t1 CREATE TABLE `t1` (
`1` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP DATABASE mysqltest1;
use test;
flush status;
show variables like "log_queries_not_using_indexes";
Variable_name Value
...
...
mysql-test/r/sp-prelocking.result
View file @
1bf318b8
...
...
@@ -289,4 +289,34 @@ create table t1 select f_bug22427() as i;
ERROR 42S01: Table 't1' already exists
drop table t1;
drop function f_bug22427;
#
# Bug #29929 LOCK TABLES does not pre-lock tables used in triggers of the locked tables
#
DROP table IF EXISTS t1,t2;
CREATE TABLE t1 (c1 INT);
CREATE TABLE t2 (c2 INT);
INSERT INTO t1 VALUES (1);
INSERT INTO t2 VALUES (2);
CREATE TRIGGER t1_ai AFTER INSERT ON t1 FOR EACH ROW
BEGIN
UPDATE t2 SET c2= c2 + 1;
END//
# Take a table lock on t1.
# This should pre-lock t2 through the trigger.
LOCK TABLE t1 WRITE;
INSERT INTO t1 VALUES (3);
UNLOCK TABLES;
LOCK TABLE t1 READ;
INSERT INTO t2 values(4);
ERROR HY000: Table 't2' was not locked with LOCK TABLES
UNLOCK TABLES;
SELECT * FROM t1;
c1
1
3
SELECT * FROM t2;
c2
3
DROP TRIGGER t1_ai;
DROP TABLE t1, t2;
End of 5.0 tests
mysql-test/t/innodb_mysql.test
View file @
1bf318b8
...
...
@@ -756,6 +756,39 @@ create table t1 (a int) engine=innodb;
alter
table
t1
alter
a
set
default
1
;
drop
table
t1
;
--
echo
--
echo
Bug
#24918 drop table and lock / inconsistent between
--
echo
perm
and
temp
tables
--
echo
--
echo
Check
transactional
tables
under
LOCK
TABLES
--
echo
--
disable_warnings
drop
table
if
exists
t24918
,
t24918_tmp
,
t24918_trans
,
t24918_trans_tmp
,
t24918_access
;
--
enable_warnings
create
table
t24918_access
(
id
int
);
create
table
t24918
(
id
int
)
engine
=
myisam
;
create
temporary
table
t24918_tmp
(
id
int
)
engine
=
myisam
;
create
table
t24918_trans
(
id
int
)
engine
=
innodb
;
create
temporary
table
t24918_trans_tmp
(
id
int
)
engine
=
innodb
;
lock
table
t24918
write
,
t24918_tmp
write
,
t24918_trans
write
,
t24918_trans_tmp
write
;
drop
table
t24918
;
--
error
ER_TABLE_NOT_LOCKED
select
*
from
t24918_access
;
drop
table
t24918_trans
;
--
error
ER_TABLE_NOT_LOCKED
select
*
from
t24918_access
;
drop
table
t24918_trans_tmp
;
--
error
ER_TABLE_NOT_LOCKED
select
*
from
t24918_access
;
drop
table
t24918_tmp
;
--
error
ER_TABLE_NOT_LOCKED
select
*
from
t24918_access
;
unlock
tables
;
drop
table
t24918_access
;
#
# Bug #28591: MySQL need not sort the records in case of ORDER BY
# primary_key on InnoDB table
...
...
mysql-test/t/show_check.test
View file @
1bf318b8
...
...
@@ -559,6 +559,10 @@ show status like 'slow_queries';
# FROM I_S.
#
#
# Part 1: check that meta-data specifies not-binary character set.
#
# Ensure that all needed objects are dropped.
--
disable_warnings
...
...
@@ -766,6 +770,59 @@ DROP VIEW v1;
DROP
PROCEDURE
p1
;
DROP
FUNCTION
f1
;
#
# Part 2: check that table with non-latin1 characters are dumped/restored
# correctly.
#
# Ensure that all needed objects are dropped.
set
names
koi8r
;
--
disable_warnings
DROP
DATABASE
IF
EXISTS
mysqltest1
;
--
enable_warnings
# Create objects.
CREATE
DATABASE
mysqltest1
;
use
mysqltest1
;
CREATE
TABLE
t1
(
1
INT
);
# Check:
# - Dump mysqltest1;
--
echo
--
echo
--->
Dumping
mysqltest1
to
show_check
.
mysqltest1
.
sql
--
exec
$MYSQL_DUMP
--
default
-
character
-
set
=
latin1
--
character
-
sets
-
dir
=
$CHARSETSDIR
--
databases
mysqltest1
>
$MYSQLTEST_VARDIR
/
tmp
/
show_check
.
mysqltest1
.
sql
# - Clean mysqltest1;
--
echo
--
echo
DROP
DATABASE
mysqltest1
;
# - Restore mysqltest1;
--
echo
--
echo
--
echo
--->
Restoring
mysqltest1
...
--
exec
$MYSQL
test
<
$MYSQLTEST_VARDIR
/
tmp
/
show_check
.
mysqltest1
.
sql
# - Check definition of the table.
SHOW
CREATE
TABLE
mysqltest1
.
t1
;
# Cleanup.
DROP
DATABASE
mysqltest1
;
use
test
;
#
# Bug #28808: log_queries_not_using_indexes variable dynamic change is ignored
#
...
...
mysql-test/t/sp-prelocking.test
View file @
1bf318b8
...
...
@@ -356,4 +356,35 @@ create table t1 select f_bug22427() as i;
drop
table
t1
;
drop
function
f_bug22427
;
--
echo
#
--
echo
# Bug #29929 LOCK TABLES does not pre-lock tables used in triggers of the locked tables
--
echo
#
--
disable_warnings
DROP
table
IF
EXISTS
t1
,
t2
;
--
enable_warnings
CREATE
TABLE
t1
(
c1
INT
);
CREATE
TABLE
t2
(
c2
INT
);
INSERT
INTO
t1
VALUES
(
1
);
INSERT
INTO
t2
VALUES
(
2
);
DELIMITER
//;
CREATE
TRIGGER
t1_ai
AFTER
INSERT
ON
t1
FOR
EACH
ROW
BEGIN
UPDATE
t2
SET
c2
=
c2
+
1
;
END
//
DELIMITER
;
//
--
echo
# Take a table lock on t1.
--
echo
# This should pre-lock t2 through the trigger.
LOCK
TABLE
t1
WRITE
;
INSERT
INTO
t1
VALUES
(
3
);
UNLOCK
TABLES
;
LOCK
TABLE
t1
READ
;
--
error
ER_TABLE_NOT_LOCKED
INSERT
INTO
t2
values
(
4
);
UNLOCK
TABLES
;
SELECT
*
FROM
t1
;
SELECT
*
FROM
t2
;
DROP
TRIGGER
t1_ai
;
DROP
TABLE
t1
,
t2
;
--
echo
End
of
5.0
tests
sql/handler.h
View file @
1bf318b8
...
...
@@ -508,6 +508,29 @@ class handler :public Sql_alloc
*/
virtual
int
rnd_init
(
bool
scan
)
=
0
;
virtual
int
rnd_end
()
{
return
0
;
}
/**
Is not invoked for non-transactional temporary tables.
Tells the storage engine that we intend to read or write data
from the table. This call is prefixed with a call to handler::store_lock()
and is invoked only for those handler instances that stored the lock.
Calls to rnd_init/index_init are prefixed with this call. When table
IO is complete, we call external_lock(F_UNLCK).
A storage engine writer should expect that each call to
::external_lock(F_[RD|WR]LOCK is followed by a call to
::external_lock(F_UNLCK). If it is not, it is a bug in MySQL.
The name and signature originate from the first implementation
in MyISAM, which would call fcntl to set/clear an advisory
lock on the data file in this method.
@param lock_type F_RDLCK, F_WRLCK, F_UNLCK
@return non-0 in case of failure, 0 in case of success.
When lock_type is F_UNLCK, the return value is ignored.
*/
virtual
int
external_lock
(
THD
*
thd
,
int
lock_type
)
{
return
0
;
}
public:
const
handlerton
*
ht
;
/* storage engine of this handler */
...
...
@@ -548,6 +571,7 @@ class handler :public Sql_alloc
uint
raid_type
,
raid_chunks
;
FT_INFO
*
ft_handler
;
enum
{
NONE
=
0
,
INDEX
,
RND
}
inited
;
bool
locked
;
bool
auto_increment_column_changed
;
bool
implicit_emptied
;
/* Can be !=0 only if HEAP */
const
COND
*
pushed_cond
;
...
...
@@ -560,10 +584,11 @@ class handler :public Sql_alloc
create_time
(
0
),
check_time
(
0
),
update_time
(
0
),
key_used_on_scan
(
MAX_KEY
),
active_index
(
MAX_KEY
),
ref_length
(
sizeof
(
my_off_t
)),
block_size
(
0
),
raid_type
(
0
),
ft_handler
(
0
),
inited
(
NONE
),
implicit_emptied
(
0
),
raid_type
(
0
),
ft_handler
(
0
),
inited
(
NONE
),
locked
(
FALSE
),
implicit_emptied
(
0
),
pushed_cond
(
NULL
)
{}
virtual
~
handler
(
void
)
{
/* TODO: DBUG_ASSERT(inited == NONE); */
}
virtual
~
handler
(
void
)
{
DBUG_ASSERT
(
locked
==
FALSE
);
/* TODO: DBUG_ASSERT(inited == NONE); */
}
virtual
handler
*
clone
(
MEM_ROOT
*
mem_root
);
int
ha_open
(
const
char
*
name
,
int
mode
,
int
test_if_locked
);
void
adjust_next_insert_id_after_explicit_value
(
ulonglong
nr
);
...
...
@@ -597,6 +622,12 @@ class handler :public Sql_alloc
virtual
const
char
*
index_type
(
uint
key_number
)
{
DBUG_ASSERT
(
0
);
return
""
;}
int
ha_external_lock
(
THD
*
thd
,
int
lock_type
)
{
DBUG_ENTER
(
"ha_external_lock"
);
locked
=
lock_type
!=
F_UNLCK
;
DBUG_RETURN
(
external_lock
(
thd
,
lock_type
));
}
int
ha_index_init
(
uint
idx
)
{
DBUG_ENTER
(
"ha_index_init"
);
...
...
@@ -689,7 +720,6 @@ class handler :public Sql_alloc
virtual
int
extra_opt
(
enum
ha_extra_function
operation
,
ulong
cache_size
)
{
return
extra
(
operation
);
}
virtual
int
reset
()
{
return
extra
(
HA_EXTRA_RESET
);
}
virtual
int
external_lock
(
THD
*
thd
,
int
lock_type
)
{
return
0
;
}
virtual
void
unlock_row
()
{}
virtual
int
start_stmt
(
THD
*
thd
,
thr_lock_type
lock_type
)
{
return
0
;}
/*
...
...
@@ -837,6 +867,9 @@ class handler :public Sql_alloc
/* lock_count() can be more than one if the table is a MERGE */
virtual
uint
lock_count
(
void
)
const
{
return
1
;
}
/**
Is not invoked for non-transactional temporary tables.
*/
virtual
THR_LOCK_DATA
**
store_lock
(
THD
*
thd
,
THR_LOCK_DATA
**
to
,
enum
thr_lock_type
lock_type
)
=
0
;
...
...
sql/lock.cc
View file @
1bf318b8
...
...
@@ -151,7 +151,8 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count,
}
thd
->
proc_info
=
"System lock"
;
if
(
lock_external
(
thd
,
tables
,
count
))
if
(
sql_lock
->
table_count
&&
lock_external
(
thd
,
sql_lock
->
table
,
sql_lock
->
table_count
))
{
/* Clear the lock type of all lock data to avoid reusage. */
reset_lock_data
(
sql_lock
);
...
...
@@ -246,12 +247,12 @@ static int lock_external(THD *thd, TABLE **tables, uint count)
(
*
tables
)
->
reginfo
.
lock_type
<=
TL_READ_NO_INSERT
))
lock_type
=
F_RDLCK
;
if
((
error
=
(
*
tables
)
->
file
->
external_lock
(
thd
,
lock_type
)))
if
((
error
=
(
*
tables
)
->
file
->
ha_
external_lock
(
thd
,
lock_type
)))
{
print_lock_error
(
error
,
(
*
tables
)
->
file
->
table_type
());
for
(;
i
--
;
tables
--
)
{
(
*
tables
)
->
file
->
external_lock
(
thd
,
F_UNLCK
);
(
*
tables
)
->
file
->
ha_
external_lock
(
thd
,
F_UNLCK
);
(
*
tables
)
->
current_lock
=
F_UNLCK
;
}
DBUG_RETURN
(
error
);
...
...
@@ -353,10 +354,28 @@ void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock)
}
/**
Try to find the table in the list of locked tables.
In case of success, unlock the table and remove it from this list.
void
mysql_lock_remove
(
THD
*
thd
,
MYSQL_LOCK
*
locked
,
TABLE
*
table
)
@note This function has a legacy side effect: the table is
unlocked even if it is not found in the locked list.
It's not clear if this side effect is intentional or still
desirable. It might lead to unmatched calls to
unlock_external(). Moreover, a discrepancy can be left
unnoticed by the storage engine, because in
unlock_external() we call handler::external_lock(F_UNLCK) only
if table->current_lock is not F_UNLCK.
@param always_unlock specify explicitly if the legacy side
effect is desired.
*/
void
mysql_lock_remove
(
THD
*
thd
,
MYSQL_LOCK
*
locked
,
TABLE
*
table
,
bool
always_unlock
)
{
mysql_unlock_some_tables
(
thd
,
&
table
,
1
);
if
(
always_unlock
==
TRUE
)
mysql_unlock_some_tables
(
thd
,
&
table
,
/* table count */
1
);
if
(
locked
)
{
reg1
uint
i
;
...
...
@@ -370,6 +389,10 @@ void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table)
DBUG_ASSERT
(
table
->
lock_position
==
i
);
/* Unlock if not yet unlocked */
if
(
always_unlock
==
FALSE
)
mysql_unlock_some_tables
(
thd
,
&
table
,
/* table count */
1
);
/* Decrement table_count in advance, making below expressions easier */
old_tables
=
--
locked
->
table_count
;
...
...
@@ -623,7 +646,7 @@ static int unlock_external(THD *thd, TABLE **table,uint count)
if
((
*
table
)
->
current_lock
!=
F_UNLCK
)
{
(
*
table
)
->
current_lock
=
F_UNLCK
;
if
((
error
=
(
*
table
)
->
file
->
external_lock
(
thd
,
F_UNLCK
)))
if
((
error
=
(
*
table
)
->
file
->
ha_
external_lock
(
thd
,
F_UNLCK
)))
{
error_code
=
error
;
print_lock_error
(
error_code
,
(
*
table
)
->
file
->
table_type
());
...
...
sql/mysql_priv.h
View file @
1bf318b8
...
...
@@ -1452,7 +1452,8 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **table, uint count,
void
mysql_unlock_tables
(
THD
*
thd
,
MYSQL_LOCK
*
sql_lock
);
void
mysql_unlock_read_tables
(
THD
*
thd
,
MYSQL_LOCK
*
sql_lock
);
void
mysql_unlock_some_tables
(
THD
*
thd
,
TABLE
**
table
,
uint
count
);
void
mysql_lock_remove
(
THD
*
thd
,
MYSQL_LOCK
*
locked
,
TABLE
*
table
);
void
mysql_lock_remove
(
THD
*
thd
,
MYSQL_LOCK
*
locked
,
TABLE
*
table
,
bool
always_unlock
);
void
mysql_lock_abort
(
THD
*
thd
,
TABLE
*
table
);
bool
mysql_lock_abort_for_thread
(
THD
*
thd
,
TABLE
*
table
);
MYSQL_LOCK
*
mysql_lock_merge
(
MYSQL_LOCK
*
a
,
MYSQL_LOCK
*
b
);
...
...
sql/opt_range.cc
View file @
1bf318b8
...
...
@@ -972,7 +972,7 @@ QUICK_RANGE_SELECT::~QUICK_RANGE_SELECT()
DBUG_PRINT
(
"info"
,
(
"Freeing separate handler 0x%lx (free: %d)"
,
(
long
)
file
,
free_file
));
file
->
reset
();
file
->
external_lock
(
current_thd
,
F_UNLCK
);
file
->
ha_
external_lock
(
current_thd
,
F_UNLCK
);
file
->
close
();
}
}
...
...
@@ -1142,7 +1142,7 @@ int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler)
/* Caller will free the memory */
goto
failure
;
/* purecov: inspected */
}
if
(
file
->
external_lock
(
thd
,
F_RDLCK
))
if
(
file
->
ha_
external_lock
(
thd
,
F_RDLCK
))
goto
failure
;
if
(
!
head
->
no_keyread
)
{
...
...
@@ -1152,7 +1152,7 @@ int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler)
if
(
file
->
extra
(
HA_EXTRA_RETRIEVE_PRIMARY_KEY
)
||
init
()
||
reset
())
{
file
->
external_lock
(
thd
,
F_UNLCK
);
file
->
ha_
external_lock
(
thd
,
F_UNLCK
);
file
->
close
();
goto
failure
;
}
...
...
sql/sp.cc
View file @
1bf318b8
...
...
@@ -273,7 +273,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
if
((
ret
=
db_find_routine_aux
(
thd
,
type
,
name
,
table
))
!=
SP_OK
)
goto
done
;
if
(
table
->
s
->
fields
!=
MYSQL_PROC_FIELD_COUNT
)
if
(
table
->
s
->
fields
<
MYSQL_PROC_FIELD_COUNT
)
{
ret
=
SP_GET_FIELD_FAILED
;
goto
done
;
...
...
@@ -523,7 +523,7 @@ db_create_routine(THD *thd, int type, sp_head *sp)
strxmov
(
definer
,
thd
->
lex
->
definer
->
user
.
str
,
"@"
,
thd
->
lex
->
definer
->
host
.
str
,
NullS
);
if
(
table
->
s
->
fields
!=
MYSQL_PROC_FIELD_COUNT
)
if
(
table
->
s
->
fields
<
MYSQL_PROC_FIELD_COUNT
)
{
ret
=
SP_GET_FIELD_FAILED
;
goto
done
;
...
...
sql/sql_base.cc
View file @
1bf318b8
...
...
@@ -1037,6 +1037,31 @@ TABLE **find_temporary_table(THD *thd, const char *db, const char *table_name)
return
0
;
// Not a temporary table
}
/**
Drop a temporary table.
Try to locate the table in the list of thd->temporary_tables.
If the table is found:
- if the table is in thd->locked_tables, unlock it and
remove it from the list of locked tables. Currently only transactional
temporary tables are present in the locked_tables list.
- Close the temporary table, remove its .FRM
- remove the table from the list of temporary tables
This function is used to drop user temporary tables, as well as
internal tables created in CREATE TEMPORARY TABLE ... SELECT
or ALTER TABLE. Even though part of the work done by this function
is redundant when the table is internal, as long as we
link both internal and user temporary tables into the same
thd->temporary_tables list, it's impossible to tell here whether
we're dealing with an internal or a user temporary table.
@retval TRUE the table was not found in the list of temporary tables
of this thread
@retval FALSE the table was found and dropped successfully.
*/
bool
close_temporary_table
(
THD
*
thd
,
const
char
*
db
,
const
char
*
table_name
)
{
TABLE
*
table
,
**
prev
;
...
...
@@ -1045,6 +1070,11 @@ bool close_temporary_table(THD *thd, const char *db, const char *table_name)
return
1
;
table
=
*
prev
;
*
prev
=
table
->
next
;
/*
If LOCK TABLES list is not empty and contains this table,
unlock the table and remove the table from this list.
*/
mysql_lock_remove
(
thd
,
thd
->
locked_tables
,
table
,
FALSE
);
close_temporary
(
table
,
1
);
if
(
thd
->
slave_thread
)
--
slave_open_temp_tables
;
...
...
@@ -1120,7 +1150,7 @@ TABLE *unlink_open_table(THD *thd, TABLE *list, TABLE *find)
!
memcmp
(
list
->
s
->
table_cache_key
,
key
,
key_length
))
{
if
(
thd
->
locked_tables
)
mysql_lock_remove
(
thd
,
thd
->
locked_tables
,
list
);
mysql_lock_remove
(
thd
,
thd
->
locked_tables
,
list
,
TRUE
);
VOID
(
hash_delete
(
&
open_cache
,(
byte
*
)
list
));
// Close table
}
else
...
...
@@ -1151,6 +1181,8 @@ TABLE *unlink_open_table(THD *thd, TABLE *list, TABLE *find)
dropped is already unlocked. In the former case it will
also remove lock on the table. But one should not rely on
this behaviour as it may change in future.
Currently, however, this function is never called for a
table that was locked with LOCK TABLES.
*/
void
drop_open_table
(
THD
*
thd
,
TABLE
*
table
,
const
char
*
db_name
,
...
...
@@ -2099,7 +2131,7 @@ bool close_data_tables(THD *thd,const char *db, const char *table_name)
if
(
!
strcmp
(
table
->
s
->
table_name
,
table_name
)
&&
!
strcmp
(
table
->
s
->
db
,
db
))
{
mysql_lock_remove
(
thd
,
thd
->
locked_tables
,
table
);
mysql_lock_remove
(
thd
,
thd
->
locked_tables
,
table
,
TRUE
);
table
->
file
->
close
();
table
->
db_stat
=
0
;
}
...
...
@@ -2239,7 +2271,7 @@ void close_old_data_files(THD *thd, TABLE *table, bool morph_locks,
instances of this table.
*/
mysql_lock_abort
(
thd
,
table
);
mysql_lock_remove
(
thd
,
thd
->
locked_tables
,
table
);
mysql_lock_remove
(
thd
,
thd
->
locked_tables
,
table
,
TRUE
);
/*
We want to protect the table from concurrent DDL operations
(like RENAME TABLE) until we will re-open and re-lock it.
...
...
@@ -2343,7 +2375,7 @@ bool drop_locked_tables(THD *thd,const char *db, const char *table_name)
if
(
!
strcmp
(
table
->
s
->
table_name
,
table_name
)
&&
!
strcmp
(
table
->
s
->
db
,
db
))
{
mysql_lock_remove
(
thd
,
thd
->
locked_tables
,
table
);
mysql_lock_remove
(
thd
,
thd
->
locked_tables
,
table
,
TRUE
);
VOID
(
hash_delete
(
&
open_cache
,(
byte
*
)
table
));
found
=
1
;
}
...
...
sql/sql_class.h
View file @
1bf318b8
...
...
@@ -995,13 +995,25 @@ enum prelocked_mode_type {NON_PRELOCKED= 0, PRELOCKED= 1,
class
Open_tables_state
{
public:
/*
open_tables - list of regular tables in use by this thread
temporary_tables - list of temp tables in use by this thread
handler_tables - list of tables that were opened with HANDLER OPEN
and are still in use by this thread
/**
List of regular tables in use by this thread. Contains temporary and
base tables that were opened with @see open_tables().
*/
TABLE
*
open_tables
;
/**
List of temporary tables used by this thread. Contains user-level
temporary tables, created with CREATE TEMPORARY TABLE, and
internal temporary tables, created, e.g., to resolve a SELECT,
or for an intermediate table used in ALTER.
XXX Why are internal temporary tables added to this list?
*/
TABLE
*
temporary_tables
;
/**
List of tables that were opened with HANDLER OPEN and are
still in use by this thread.
*/
TABLE
*
open_tables
,
*
temporary_tables
,
*
handler_tables
,
*
derived_tables
;
TABLE
*
handler_tables
;
TABLE
*
derived_tables
;
/*
During a MySQL session, one can lock tables in two modes: automatic
or manual. In automatic mode all necessary tables are locked just before
...
...
sql/sql_lex.cc
View file @
1bf318b8
...
...
@@ -2035,12 +2035,129 @@ void st_select_lex_unit::set_limit(SELECT_LEX *sl)
/**
Update the parsed tree with information about triggers that
may be fired when executing this statement.
@brief Set the initial purpose of this TABLE_LIST object in the list of used
tables.
We need to track this information on table-by-table basis, since when this
table becomes an element of the pre-locked list, it's impossible to identify
which SQL sub-statement it has been originally used in.
E.g.:
User request: SELECT * FROM t1 WHERE f1();
FUNCTION f1(): DELETE FROM t2; RETURN 1;
BEFORE DELETE trigger on t2: INSERT INTO t3 VALUES (old.a);
For this user request, the pre-locked list will contain t1, t2, t3
table elements, each needed for different DML.
The trigger event map is updated to reflect INSERT, UPDATE, DELETE,
REPLACE, LOAD DATA, CREATE TABLE .. SELECT, CREATE TABLE ..
REPLACE SELECT statements, and additionally ON DUPLICATE KEY UPDATE
clause.
*/
void
st_lex
::
set_trg_event_type_for_tables
()
{
uint8
new_trg_event_map
=
0
;
/*
Some auxiliary operations
(e.g. GRANT processing) create TABLE_LIST instances outside
the parser. Additionally, some commands (e.g. OPTIMIZE) change
the lock type for a table only after parsing is done. Luckily,
these do not fire triggers and do not need to pre-load them.
For these TABLE_LISTs set_trg_event_type is never called, and
trg_event_map is always empty. That means that the pre-locking
algorithm will ignore triggers defined on these tables, if
any, and the execution will either fail with an assert in
sql_trigger.cc or with an error that a used table was not
pre-locked, in case of a production build.
TODO: this usage pattern creates unnecessary module dependencies
and should be rewritten to go through the parser.
Table list instances created outside the parser in most cases
refer to mysql.* system tables. It is not allowed to have
a trigger on a system table, but keeping track of
initialization provides extra safety in case this limitation
is circumvented.
*/
switch
(
sql_command
)
{
case
SQLCOM_LOCK_TABLES
:
/*
On a LOCK TABLE, all triggers must be pre-loaded for this TABLE_LIST
when opening an associated TABLE.
*/
new_trg_event_map
=
static_cast
<
uint8
>
(
1
<<
static_cast
<
int
>
(
TRG_EVENT_INSERT
))
|
static_cast
<
uint8
>
(
1
<<
static_cast
<
int
>
(
TRG_EVENT_UPDATE
))
|
static_cast
<
uint8
>
(
1
<<
static_cast
<
int
>
(
TRG_EVENT_DELETE
));
break
;
/*
Basic INSERT. If there is an additional ON DUPLIATE KEY UPDATE
clause, it will be handled later in this method.
*/
case
SQLCOM_INSERT
:
/* fall through */
case
SQLCOM_INSERT_SELECT
:
/*
LOAD DATA ... INFILE is expected to fire BEFORE/AFTER INSERT
triggers.
If the statement also has REPLACE clause, it will be
handled later in this method.
*/
case
SQLCOM_LOAD
:
/* fall through */
/*
REPLACE is semantically equivalent to INSERT. In case
of a primary or unique key conflict, it deletes the old
record and inserts a new one. So we also may need to
fire ON DELETE triggers. This functionality is handled
later in this method.
*/
case
SQLCOM_REPLACE
:
/* fall through */
case
SQLCOM_REPLACE_SELECT
:
/*
CREATE TABLE ... SELECT defaults to INSERT if the table or
view already exists. REPLACE option of CREATE TABLE ...
REPLACE SELECT is handled later in this method.
*/
case
SQLCOM_CREATE_TABLE
:
new_trg_event_map
|=
static_cast
<
uint8
>
(
1
<<
static_cast
<
int
>
(
TRG_EVENT_INSERT
));
break
;
/* Basic update and multi-update */
case
SQLCOM_UPDATE
:
/* fall through */
case
SQLCOM_UPDATE_MULTI
:
new_trg_event_map
|=
static_cast
<
uint8
>
(
1
<<
static_cast
<
int
>
(
TRG_EVENT_UPDATE
));
break
;
/* Basic delete and multi-delete */
case
SQLCOM_DELETE
:
/* fall through */
case
SQLCOM_DELETE_MULTI
:
new_trg_event_map
|=
static_cast
<
uint8
>
(
1
<<
static_cast
<
int
>
(
TRG_EVENT_DELETE
));
break
;
default:
break
;
}
switch
(
duplicates
)
{
case
DUP_UPDATE
:
new_trg_event_map
|=
static_cast
<
uint8
>
(
1
<<
static_cast
<
int
>
(
TRG_EVENT_UPDATE
));
break
;
case
DUP_REPLACE
:
new_trg_event_map
|=
static_cast
<
uint8
>
(
1
<<
static_cast
<
int
>
(
TRG_EVENT_DELETE
));
break
;
case
DUP_ERROR
:
default:
break
;
}
/*
Do not iterate over sub-selects, only the tables in the outermost
SELECT_LEX can be modified, if any.
...
...
@@ -2049,7 +2166,17 @@ void st_lex::set_trg_event_type_for_tables()
while
(
tables
)
{
tables
->
set_trg_event_type
(
this
);
/*
This is a fast check to filter out statements that do
not change data, or tables on the right side, in case of
INSERT .. SELECT, CREATE TABLE .. SELECT and so on.
Here we also filter out OPTIMIZE statement and non-updateable
views, for which lock_type is TL_UNLOCK or TL_READ after
parsing.
*/
if
(
static_cast
<
int
>
(
tables
->
lock_type
)
>=
static_cast
<
int
>
(
TL_WRITE_ALLOW_WRITE
))
tables
->
trg_event_map
=
new_trg_event_map
;
tables
=
tables
->
next_local
;
}
}
...
...
sql/sql_table.cc
View file @
1bf318b8
...
...
@@ -3811,7 +3811,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
The following function call will free the new_table pointer,
in close_temporary_table(), so we can safely directly jump to err
*/
close_temporary_table
(
thd
,
new_db
,
tmp_name
);
close_temporary_table
(
thd
,
new_db
,
tmp_name
);
goto
err
;
}
/* Close lock if this is a transactional table */
...
...
@@ -4084,7 +4084,7 @@ copy_data_between_tables(TABLE *from,TABLE *to,
if
(
!
(
copy
=
new
Copy_field
[
to
->
s
->
fields
]))
DBUG_RETURN
(
-
1
);
/* purecov: inspected */
if
(
to
->
file
->
external_lock
(
thd
,
F_WRLCK
))
if
(
to
->
file
->
ha_
external_lock
(
thd
,
F_WRLCK
))
DBUG_RETURN
(
-
1
);
/* We need external lock before we can disable/enable keys */
...
...
@@ -4236,7 +4236,7 @@ copy_data_between_tables(TABLE *from,TABLE *to,
free_io_cache
(
from
);
*
copied
=
found_count
;
*
deleted
=
delete_count
;
if
(
to
->
file
->
external_lock
(
thd
,
F_UNLCK
))
if
(
to
->
file
->
ha_
external_lock
(
thd
,
F_UNLCK
))
error
=
1
;
DBUG_RETURN
(
error
>
0
?
-
1
:
0
);
}
...
...
sql/sql_yacc.yy
View file @
1bf318b8
...
...
@@ -5567,7 +5567,7 @@ join_table:
so that [INNER | CROSS] JOIN is properly nested as other
left-associative joins.
*/
table_ref
%prec TABLE_REF_PRIORITY normal_join table_ref
table_ref
normal_join table_ref %prec TABLE_REF_PRIORITY
{ MYSQL_YYABORT_UNLESS($1 && ($$=$3)); }
| table_ref STRAIGHT_JOIN table_factor
{ MYSQL_YYABORT_UNLESS($1 && ($$=$3)); $3->straight=1; }
...
...
sql/table.cc
View file @
1bf318b8
...
...
@@ -1781,135 +1781,6 @@ void st_table::reset_item_list(List<Item> *item_list) const
}
}
/**
Set the initial purpose of this TABLE_LIST object in the list of
used tables. We need to track this information on table-by-
table basis, since when this table becomes an element of the
pre-locked list, it's impossible to identify which SQL
sub-statement it has been originally used in.
E.g.:
User request: SELECT * FROM t1 WHERE f1();
FUNCTION f1(): DELETE FROM t2; RETURN 1;
BEFORE DELETE trigger on t2: INSERT INTO t3 VALUES (old.a);
For this user request, the pre-locked list will contain t1, t2, t3
table elements, each needed for different DML.
This method is called immediately after parsing for tables
of the table list of the top-level select lex.
The trigger event map is updated to reflect INSERT, UPDATE, DELETE,
REPLACE, LOAD DATA, CREATE TABLE .. SELECT, CREATE TABLE ..
REPLACE SELECT statements, and additionally ON DUPLICATE KEY UPDATE
clause.
*/
void
TABLE_LIST
::
set_trg_event_type
(
const
st_lex
*
lex
)
{
enum
trg_event_type
trg_event
;
/*
Some auxiliary operations
(e.g. GRANT processing) create TABLE_LIST instances outside
the parser. Additionally, some commands (e.g. OPTIMIZE) change
the lock type for a table only after parsing is done. Luckily,
these do not fire triggers and do not need to pre-load them.
For these TABLE_LISTs set_trg_event_type is never called, and
trg_event_map is always empty. That means that the pre-locking
algorithm will ignore triggers defined on these tables, if
any, and the execution will either fail with an assert in
sql_trigger.cc or with an error that a used table was not
pre-locked, in case of a production build.
TODO: this usage pattern creates unnecessary module dependencies
and should be rewritten to go through the parser.
Table list instances created outside the parser in most cases
refer to mysql.* system tables. It is not allowed to have
a trigger on a system table, but keeping track of
initialization provides extra safety in case this limitation
is circumvented.
*/
/*
This is a fast check to filter out statements that do
not change data, or tables on the right side, in case of
INSERT .. SELECT, CREATE TABLE .. SELECT and so on.
Here we also filter out OPTIMIZE statement and non-updateable
views, for which lock_type is TL_UNLOCK or TL_READ after
parsing.
*/
if
(
static_cast
<
int
>
(
lock_type
)
<
static_cast
<
int
>
(
TL_WRITE_ALLOW_WRITE
))
return
;
switch
(
lex
->
sql_command
)
{
/*
Basic INSERT. If there is an additional ON DUPLIATE KEY UPDATE
clause, it will be handled later in this method.
*/
case
SQLCOM_INSERT
:
/* fall through */
case
SQLCOM_INSERT_SELECT
:
/*
LOAD DATA ... INFILE is expected to fire BEFORE/AFTER INSERT
triggers.
If the statement also has REPLACE clause, it will be
handled later in this method.
*/
case
SQLCOM_LOAD
:
/* fall through */
/*
REPLACE is semantically equivalent to INSERT. In case
of a primary or unique key conflict, it deletes the old
record and inserts a new one. So we also may need to
fire ON DELETE triggers. This functionality is handled
later in this method.
*/
case
SQLCOM_REPLACE
:
/* fall through */
case
SQLCOM_REPLACE_SELECT
:
/*
CREATE TABLE ... SELECT defaults to INSERT if the table or
view already exists. REPLACE option of CREATE TABLE ...
REPLACE SELECT is handled later in this method.
*/
case
SQLCOM_CREATE_TABLE
:
trg_event
=
TRG_EVENT_INSERT
;
break
;
/* Basic update and multi-update */
case
SQLCOM_UPDATE
:
/* fall through */
case
SQLCOM_UPDATE_MULTI
:
trg_event
=
TRG_EVENT_UPDATE
;
break
;
/* Basic delete and multi-delete */
case
SQLCOM_DELETE
:
/* fall through */
case
SQLCOM_DELETE_MULTI
:
trg_event
=
TRG_EVENT_DELETE
;
break
;
default:
/*
OK to return, since value of 'duplicates' is irrelevant
for non-updating commands.
*/
return
;
}
trg_event_map
|=
static_cast
<
uint8
>
(
1
<<
static_cast
<
int
>
(
trg_event
));
switch
(
lex
->
duplicates
)
{
case
DUP_UPDATE
:
trg_event
=
TRG_EVENT_UPDATE
;
break
;
case
DUP_REPLACE
:
trg_event
=
TRG_EVENT_DELETE
;
break
;
case
DUP_ERROR
:
default:
return
;
}
trg_event_map
|=
static_cast
<
uint8
>
(
1
<<
static_cast
<
int
>
(
trg_event
));
}
/*
calculate md5 of query
...
...
sql/table.h
View file @
1bf318b8
...
...
@@ -770,7 +770,6 @@ struct TABLE_LIST
void
reinit_before_use
(
THD
*
thd
);
Item_subselect
*
containing_subselect
();
void
set_trg_event_type
(
const
st_lex
*
lex
);
private:
bool
prep_check_option
(
THD
*
thd
,
uint8
check_opt_type
);
bool
prep_where
(
THD
*
thd
,
Item
**
conds
,
bool
no_where_clause
);
...
...
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