Merge branch '5.5' into 10.1
This commit is contained in:
commit
2ce52790ff
@ -123,6 +123,26 @@ View Create View character_set_client collation_connection
|
||||
v3 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v3` AS select `t_select_priv`.`a` AS `a`,`t_select_priv`.`b` AS `b` from `t_select_priv` latin1 latin1_swedish_ci
|
||||
drop database mysqltest_db1;
|
||||
drop user mysqltest_u1@localhost;
|
||||
call mtr.add_suppression("Table 'mysql.user' doesn't exist");
|
||||
call mtr.add_suppression("'mysql.user' is not TABLE");
|
||||
rename table mysql.user to mysql.user1;
|
||||
create view mysql.user as select * from mysql.user1;
|
||||
flush privileges;
|
||||
ERROR HY000: 'mysql.user' is not TABLE
|
||||
drop view mysql.user;
|
||||
create temporary table mysql.user select * from mysql.user1 limit 0;
|
||||
flush privileges;
|
||||
ERROR 42S02: Table 'mysql.user' doesn't exist
|
||||
drop temporary table mysql.user;
|
||||
rename table mysql.user1 to mysql.user;
|
||||
call mtr.add_suppression('mysql.user table is damaged');
|
||||
rename table mysql.user to mysql.user1;
|
||||
create table mysql.user (Host char(100), User char(100));
|
||||
flush privileges;
|
||||
ERROR HY000: Unknown error
|
||||
drop table mysql.user;
|
||||
rename table mysql.user1 to mysql.user;
|
||||
End of 5.5 tests
|
||||
#
|
||||
# Additional coverage for refactoring which is made as part
|
||||
# of fix for bug #27480 "Extend CREATE TEMPORARY TABLES privilege
|
||||
@ -215,3 +235,4 @@ ERROR HY000: Password hash should be a 16-digit hexadecimal number
|
||||
create user foo4 identified via mysql_old_password using '11111111111111111111111111111111111111111';
|
||||
ERROR HY000: Password hash should be a 16-digit hexadecimal number
|
||||
set GLOBAL sql_mode=default;
|
||||
End of 10.1 tests
|
||||
|
4
mysql-test/r/information_schema_prepare.result
Normal file
4
mysql-test/r/information_schema_prepare.result
Normal file
@ -0,0 +1,4 @@
|
||||
PREPARE stmt2 FROM "CREATE VIEW v AS SELECT * FROM INFORMATION_SCHEMA.TABLES";
|
||||
FLUSH PRIVILEGES;
|
||||
EXECUTE stmt2;
|
||||
DROP VIEW v;
|
@ -1018,6 +1018,27 @@ execute stmt1;
|
||||
deallocate prepare stmt1;
|
||||
drop view v3,v2,v1;
|
||||
drop table t1,t2,t3;
|
||||
create table t1 (id int not null, v1 varchar(10) not null);
|
||||
insert into t1 values (1,1),(2,2);
|
||||
create table t2 (log varchar(10) not null);
|
||||
create trigger t1_after_update after update on t1
|
||||
for each row insert into t2 values ('triggered');
|
||||
create user foo;
|
||||
grant select, insert, update, delete, create, drop, reload, index, alter, show databases, create temporary tables, lock tables, execute, create view, show view, create routine, alter routine, trigger on *.* to 'foo'@'%';
|
||||
set global read_only=1;
|
||||
create temporary table temp_t1 (id int not null, update_me varchar(10));
|
||||
insert into temp_t1 values (1,1),(2,2),(3,3);
|
||||
update temp_t1 left join t1 on temp_t1.id = t1.id set temp_t1.update_me = 'hello';
|
||||
set global read_only = 0;
|
||||
create table t3 (id int not null);
|
||||
insert t3 values (2);
|
||||
update t1 left join t3 on t1.id = t3.id set t1.v1 = 'hello';
|
||||
select * from t2;
|
||||
log
|
||||
triggered
|
||||
triggered
|
||||
drop table t1,t2, t3;
|
||||
drop user foo;
|
||||
end of 5.5 tests
|
||||
|
||||
# Bug mdev-5970
|
||||
|
@ -177,12 +177,15 @@ create table mysqltest.t1 (a int, b int, primary key(a));
|
||||
insert into mysqltest.t1 values (10,2), (20,3), (30,4), (40,5), (50,10);
|
||||
create table mysqltest.t2 (x int);
|
||||
insert into mysqltest.t2 values (3), (4), (5), (6);
|
||||
create table mysqltest.t3 (x int);
|
||||
insert into mysqltest.t3 values (3), (4), (5), (6);
|
||||
create view mysqltest.v1 (a,c) as select a, b+1 from mysqltest.t1;
|
||||
create view mysqltest.v2 (a,c) as select a, b from mysqltest.t1;
|
||||
create view mysqltest.v3 (a,c) as select a, b+1 from mysqltest.t1;
|
||||
create user mysqltest_1@localhost;
|
||||
grant update (a) on mysqltest.v2 to mysqltest_1@localhost;
|
||||
grant update on mysqltest.v1 to mysqltest_1@localhost;
|
||||
grant update on mysqltest.t3 to mysqltest_1@localhost;
|
||||
grant select on mysqltest.* to mysqltest_1@localhost;
|
||||
use mysqltest;
|
||||
update t2,v1 set v1.a=v1.a+v1.c where t2.x=v1.c;
|
||||
@ -217,6 +220,7 @@ a b
|
||||
48 4
|
||||
62 5
|
||||
71 10
|
||||
update t3,v3 set t3.x=t3.x+v3.c where t3.x=v3.c;
|
||||
update t2,v2 set v2.c=v2.a+v2.c where t2.x=v2.c;
|
||||
ERROR 42000: UPDATE command denied to user 'mysqltest_1'@'localhost' for column 'c' in table 'v2'
|
||||
update v2 set c=a+c;
|
||||
|
@ -66,3 +66,16 @@ a
|
||||
1
|
||||
2
|
||||
DROP TABLE t1;
|
||||
call mtr.add_suppression('InnoDB: Error: in RENAME TABLE table `test`.`t3`');
|
||||
SET FOREIGN_KEY_CHECKS= OFF;
|
||||
CREATE TABLE t1 (f2 INT, f4 INT, KEY(f2), FOREIGN KEY (f4) REFERENCES t3 (f4)) ENGINE=InnoDB;
|
||||
SET FOREIGN_KEY_CHECKS= ON;
|
||||
CREATE TABLE t2 (f2 INT, FOREIGN KEY(f2) REFERENCES t1 (f2)) ENGINE=InnoDB;
|
||||
CREATE TABLE t3 (a INT) ENGINE=InnoDB;
|
||||
ERROR HY000: Can't create table `test`.`t3` (errno: 150 "Foreign key constraint is incorrectly formed")
|
||||
ALTER TABLE t1 RENAME TO t3;
|
||||
ERROR HY000: Error on rename of './test/t1' to './test/t3' (errno: 150 "Foreign key constraint is incorrectly formed")
|
||||
ALTER TABLE t1 FORCE;
|
||||
TRUNCATE TABLE t1;
|
||||
ERROR 42000: Cannot truncate a table referenced in a foreign key constraint (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f2`) REFERENCES `test`.`t3` (`f2`))
|
||||
DROP TABLE t2, t1;
|
||||
|
@ -1,4 +1,5 @@
|
||||
--source include/have_innodb.inc
|
||||
let $datadir=`select @@datadir`;
|
||||
--echo #
|
||||
--echo # TRUNCATE TABLE
|
||||
--echo #
|
||||
@ -62,3 +63,20 @@ INSERT INTO t1 VALUES (NULL), (NULL);
|
||||
SELECT * FROM t1 ORDER BY a;
|
||||
DROP TABLE t1;
|
||||
|
||||
#
|
||||
# MDEV-18923 Assertion `!lex_string_cmp(system_charset_info, fk_info->referenced_table, &table->s->table_name)' failed in fk_truncate_illegal_if_parent
|
||||
#
|
||||
call mtr.add_suppression('InnoDB: Error: in RENAME TABLE table `test`.`t3`');
|
||||
SET FOREIGN_KEY_CHECKS= OFF;
|
||||
CREATE TABLE t1 (f2 INT, f4 INT, KEY(f2), FOREIGN KEY (f4) REFERENCES t3 (f4)) ENGINE=InnoDB;
|
||||
SET FOREIGN_KEY_CHECKS= ON;
|
||||
CREATE TABLE t2 (f2 INT, FOREIGN KEY(f2) REFERENCES t1 (f2)) ENGINE=InnoDB;
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
CREATE TABLE t3 (a INT) ENGINE=InnoDB;
|
||||
--replace_result $datadir ./
|
||||
--error ER_ERROR_ON_RENAME
|
||||
ALTER TABLE t1 RENAME TO t3;
|
||||
ALTER TABLE t1 FORCE;
|
||||
--error ER_TRUNCATE_ILLEGAL_FK
|
||||
TRUNCATE TABLE t1;
|
||||
DROP TABLE t2, t1;
|
||||
|
13
mysql-test/suite/rpl/r/kill_race_condition.result
Normal file
13
mysql-test/suite/rpl/r/kill_race_condition.result
Normal file
@ -0,0 +1,13 @@
|
||||
include/master-slave.inc
|
||||
[connection master]
|
||||
set global debug_dbug='d,rows_log_event_before_open_table';
|
||||
set debug_sync='now WAIT_FOR before_open_table';
|
||||
create table t1 (a int);
|
||||
insert t1 values (1),(2),(3);
|
||||
kill slave_sql_thread;
|
||||
set debug_sync='now SIGNAL go_ahead_sql';
|
||||
set global debug_dbug='';
|
||||
set debug_sync='RESET';
|
||||
drop table t1;
|
||||
start slave;
|
||||
include/rpl_end.inc
|
28
mysql-test/suite/rpl/t/kill_race_condition.test
Normal file
28
mysql-test/suite/rpl/t/kill_race_condition.test
Normal file
@ -0,0 +1,28 @@
|
||||
source include/have_debug_sync.inc;
|
||||
source include/have_binlog_format_row.inc;
|
||||
source include/master-slave.inc;
|
||||
|
||||
connection slave;
|
||||
set global debug_dbug='d,rows_log_event_before_open_table';
|
||||
send set debug_sync='now WAIT_FOR before_open_table';
|
||||
|
||||
connection master;
|
||||
create table t1 (a int);
|
||||
insert t1 values (1),(2),(3);
|
||||
|
||||
connection slave;
|
||||
reap;
|
||||
let $a=`select id from information_schema.processlist where state='debug sync point: now'`;
|
||||
replace_result $a slave_sql_thread;
|
||||
eval kill $a;
|
||||
set debug_sync='now SIGNAL go_ahead_sql';
|
||||
set global debug_dbug='';
|
||||
set debug_sync='RESET';
|
||||
|
||||
connection master;
|
||||
drop table t1;
|
||||
|
||||
connection slave;
|
||||
start slave;
|
||||
|
||||
source include/rpl_end.inc;
|
@ -145,6 +145,34 @@ disconnect con1;
|
||||
drop database mysqltest_db1;
|
||||
drop user mysqltest_u1@localhost;
|
||||
|
||||
#
|
||||
# MDEV-18241 Downgrade from 10.4 to 10.3 crashes
|
||||
#
|
||||
call mtr.add_suppression("Table 'mysql.user' doesn't exist");
|
||||
call mtr.add_suppression("'mysql.user' is not TABLE");
|
||||
rename table mysql.user to mysql.user1;
|
||||
create view mysql.user as select * from mysql.user1;
|
||||
--error ER_WRONG_OBJECT
|
||||
flush privileges;
|
||||
drop view mysql.user;
|
||||
create temporary table mysql.user select * from mysql.user1 limit 0;
|
||||
--error ER_NO_SUCH_TABLE
|
||||
flush privileges;
|
||||
drop temporary table mysql.user;
|
||||
rename table mysql.user1 to mysql.user;
|
||||
|
||||
#
|
||||
# Bug#28986737: RENAMING AND REPLACING MYSQL.USER TABLE CAN LEAD TO A SERVER CRASH
|
||||
#
|
||||
call mtr.add_suppression('mysql.user table is damaged');
|
||||
rename table mysql.user to mysql.user1;
|
||||
create table mysql.user (Host char(100), User char(100));
|
||||
--error ER_UNKNOWN_ERROR
|
||||
flush privileges;
|
||||
drop table mysql.user;
|
||||
rename table mysql.user1 to mysql.user;
|
||||
|
||||
--echo End of 5.5 tests
|
||||
|
||||
--echo #
|
||||
--echo # Additional coverage for refactoring which is made as part
|
||||
@ -235,5 +263,6 @@ create user foo3 identified via mysql_old_password using '00';
|
||||
--error ER_PASSWD_LENGTH
|
||||
create user foo4 identified via mysql_old_password using '11111111111111111111111111111111111111111';
|
||||
|
||||
|
||||
set GLOBAL sql_mode=default;
|
||||
|
||||
--echo End of 10.1 tests
|
||||
|
7
mysql-test/t/information_schema_prepare.test
Normal file
7
mysql-test/t/information_schema_prepare.test
Normal file
@ -0,0 +1,7 @@
|
||||
#
|
||||
# MDEV-15907 ASAN heap-use-after-free in strnmov / .. / fill_effective_table_privileges on concurrent GRANT and CREATE VIEW
|
||||
#
|
||||
PREPARE stmt2 FROM "CREATE VIEW v AS SELECT * FROM INFORMATION_SCHEMA.TABLES";
|
||||
FLUSH PRIVILEGES;
|
||||
EXECUTE stmt2;
|
||||
DROP VIEW v;
|
@ -1056,6 +1056,37 @@ deallocate prepare stmt1;
|
||||
|
||||
drop view v3,v2,v1;
|
||||
drop table t1,t2,t3;
|
||||
|
||||
#
|
||||
# MDEV-18507 can't update temporary table when joined with table with triggers on read-only
|
||||
#
|
||||
create table t1 (id int not null, v1 varchar(10) not null);
|
||||
insert into t1 values (1,1),(2,2);
|
||||
create table t2 (log varchar(10) not null);
|
||||
create trigger t1_after_update after update on t1
|
||||
for each row insert into t2 values ('triggered');
|
||||
|
||||
create user foo;
|
||||
grant select, insert, update, delete, create, drop, reload, index, alter, show databases, create temporary tables, lock tables, execute, create view, show view, create routine, alter routine, trigger on *.* to 'foo'@'%';
|
||||
|
||||
set global read_only=1;
|
||||
connect a, localhost, foo;
|
||||
|
||||
create temporary table temp_t1 (id int not null, update_me varchar(10));
|
||||
insert into temp_t1 values (1,1),(2,2),(3,3);
|
||||
update temp_t1 left join t1 on temp_t1.id = t1.id set temp_t1.update_me = 'hello';
|
||||
|
||||
connection default;
|
||||
set global read_only = 0;
|
||||
|
||||
create table t3 (id int not null);
|
||||
insert t3 values (2);
|
||||
update t1 left join t3 on t1.id = t3.id set t1.v1 = 'hello';
|
||||
select * from t2;
|
||||
|
||||
drop table t1,t2, t3;
|
||||
drop user foo;
|
||||
|
||||
--echo end of 5.5 tests
|
||||
|
||||
|
||||
|
@ -244,6 +244,8 @@ create table mysqltest.t1 (a int, b int, primary key(a));
|
||||
insert into mysqltest.t1 values (10,2), (20,3), (30,4), (40,5), (50,10);
|
||||
create table mysqltest.t2 (x int);
|
||||
insert into mysqltest.t2 values (3), (4), (5), (6);
|
||||
create table mysqltest.t3 (x int);
|
||||
insert into mysqltest.t3 values (3), (4), (5), (6);
|
||||
create view mysqltest.v1 (a,c) as select a, b+1 from mysqltest.t1;
|
||||
create view mysqltest.v2 (a,c) as select a, b from mysqltest.t1;
|
||||
create view mysqltest.v3 (a,c) as select a, b+1 from mysqltest.t1;
|
||||
@ -251,6 +253,7 @@ create view mysqltest.v3 (a,c) as select a, b+1 from mysqltest.t1;
|
||||
create user mysqltest_1@localhost;
|
||||
grant update (a) on mysqltest.v2 to mysqltest_1@localhost;
|
||||
grant update on mysqltest.v1 to mysqltest_1@localhost;
|
||||
grant update on mysqltest.t3 to mysqltest_1@localhost;
|
||||
grant select on mysqltest.* to mysqltest_1@localhost;
|
||||
|
||||
connection user1;
|
||||
@ -265,6 +268,8 @@ update t2,v2 set v2.a=v2.a+v2.c where t2.x=v2.c;
|
||||
select * from t1;
|
||||
update v2 set a=a+c;
|
||||
select * from t1;
|
||||
# update a table, select only on view
|
||||
update t3,v3 set t3.x=t3.x+v3.c where t3.x=v3.c;
|
||||
# no rights on column
|
||||
--error ER_COLUMNACCESS_DENIED_ERROR
|
||||
update t2,v2 set v2.c=v2.a+v2.c where t2.x=v2.c;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Copyright (c) 2000, 2018, Oracle and/or its affiliates.
|
||||
Copyright (c) 2009, 2018, MariaDB
|
||||
Copyright (c) 2000, 2019, Oracle and/or its affiliates.
|
||||
Copyright (c) 2009, 2019, MariaDB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -40,6 +40,7 @@
|
||||
#include "transaction.h"
|
||||
#include <my_dir.h>
|
||||
#include "sql_show.h" // append_identifier
|
||||
#include "debug_sync.h" // debug_sync
|
||||
#include <mysql/psi/mysql_statement.h>
|
||||
#include <strfunc.h>
|
||||
#include "compat56.h"
|
||||
@ -9910,6 +9911,12 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
|
||||
/* A small test to verify that objects have consistent types */
|
||||
DBUG_ASSERT(sizeof(thd->variables.option_bits) == sizeof(OPTION_RELAXED_UNIQUE_CHECKS));
|
||||
|
||||
DBUG_EXECUTE_IF("rows_log_event_before_open_table",
|
||||
{
|
||||
const char action[] = "now SIGNAL before_open_table WAIT_FOR go_ahead_sql";
|
||||
DBUG_ASSERT(!debug_sync_set_action(thd, STRING_WITH_LEN(action)));
|
||||
};);
|
||||
|
||||
if (slave_run_triggers_for_rbr)
|
||||
{
|
||||
LEX *lex= thd->lex;
|
||||
@ -9934,7 +9941,6 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
|
||||
}
|
||||
if (open_and_lock_tables(thd, rgi->tables_to_lock, FALSE, 0))
|
||||
{
|
||||
uint actual_error= thd->get_stmt_da()->sql_errno();
|
||||
#ifdef WITH_WSREP
|
||||
if (WSREP(thd))
|
||||
{
|
||||
@ -9947,23 +9953,22 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
|
||||
(long long)wsrep_thd_trx_seqno(thd));
|
||||
}
|
||||
#endif
|
||||
if ((thd->is_slave_error || thd->is_fatal_error) &&
|
||||
!is_parallel_retry_error(rgi, actual_error))
|
||||
if (thd->is_error() &&
|
||||
!is_parallel_retry_error(rgi, error= thd->get_stmt_da()->sql_errno()))
|
||||
{
|
||||
/*
|
||||
Error reporting borrowed from Query_log_event with many excessive
|
||||
simplifications.
|
||||
simplifications.
|
||||
We should not honour --slave-skip-errors at this point as we are
|
||||
having severe errors which should not be skiped.
|
||||
having severe errors which should not be skipped.
|
||||
*/
|
||||
rli->report(ERROR_LEVEL, actual_error, rgi->gtid_info(),
|
||||
rli->report(ERROR_LEVEL, error, rgi->gtid_info(),
|
||||
"Error executing row event: '%s'",
|
||||
(actual_error ? thd->get_stmt_da()->message() :
|
||||
(error ? thd->get_stmt_da()->message() :
|
||||
"unexpected success or fatal error"));
|
||||
thd->is_slave_error= 1;
|
||||
}
|
||||
/* remove trigger's tables */
|
||||
error= actual_error;
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Copyright (c) 2007, 2018, Oracle and/or its affiliates.
|
||||
Copyright (c) 2009, 2018, MariaDB
|
||||
/* Copyright (c) 2007, 2019, Oracle and/or its affiliates.
|
||||
Copyright (c) 2009, 2019, MariaDB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -101,21 +101,20 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, rpl_group_info *rgi)
|
||||
|
||||
if (open_and_lock_tables(ev_thd, rgi->tables_to_lock, FALSE, 0))
|
||||
{
|
||||
uint actual_error= ev_thd->get_stmt_da()->sql_errno();
|
||||
if (ev_thd->is_slave_error || ev_thd->is_fatal_error)
|
||||
if (ev_thd->is_error())
|
||||
{
|
||||
/*
|
||||
Error reporting borrowed from Query_log_event with many excessive
|
||||
simplifications (we don't honour --slave-skip-errors)
|
||||
simplifications.
|
||||
We should not honour --slave-skip-errors at this point as we are
|
||||
having severe errors which should not be skipped.
|
||||
*/
|
||||
rli->report(ERROR_LEVEL, actual_error, NULL,
|
||||
rli->report(ERROR_LEVEL, ev_thd->get_stmt_da()->sql_errno(), NULL,
|
||||
"Error '%s' on opening tables",
|
||||
(actual_error ? ev_thd->get_stmt_da()->message() :
|
||||
"unexpected success or fatal error"));
|
||||
ev_thd->get_stmt_da()->message());
|
||||
ev_thd->is_slave_error= 1;
|
||||
}
|
||||
rgi->slave_close_thread_tables(thd);
|
||||
DBUG_RETURN(actual_error);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1271,6 +1271,13 @@ static bool acl_load(THD *thd, TABLE_LIST *tables)
|
||||
goto end;
|
||||
table->use_all_columns();
|
||||
|
||||
if (table->s->fields < 13) // number of columns in 3.21
|
||||
{
|
||||
sql_print_error("Fatal error: mysql.user table is damaged or in "
|
||||
"unsupported 3.20 format.");
|
||||
goto end;
|
||||
}
|
||||
|
||||
username_char_length= MY_MIN(table->field[1]->char_length(),
|
||||
USERNAME_CHAR_LENGTH);
|
||||
password_length= table->field[2]->field_length /
|
||||
@ -8550,8 +8557,7 @@ static int open_grant_tables(THD *thd, TABLE_LIST *tables,
|
||||
acl_table_names[cur].length,
|
||||
acl_table_names[cur].str, lock_type);
|
||||
tables[cur].open_type= OT_BASE_ONLY;
|
||||
if (lock_type >= TL_WRITE_ALLOW_WRITE)
|
||||
tables[cur].updating= 1;
|
||||
tables[cur].i_s_requested_object= OPEN_TABLE_ONLY;
|
||||
if (cur >= FIRST_OPTIONAL_TABLE)
|
||||
tables[cur].open_strategy= TABLE_LIST::OPEN_IF_EXISTS;
|
||||
if (prev != -1)
|
||||
|
@ -3923,6 +3923,45 @@ open_and_process_routine(THD *thd, Query_tables_list *prelocking_ctx,
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
If we are not already in prelocked mode and extended table list is not
|
||||
yet built we might have to build the prelocking set for this statement.
|
||||
|
||||
Since currently no prelocking strategy prescribes doing anything for
|
||||
tables which are only read, we do below checks only if table is going
|
||||
to be changed.
|
||||
*/
|
||||
bool extend_table_list(THD *thd, TABLE_LIST *tables,
|
||||
Prelocking_strategy *prelocking_strategy,
|
||||
bool has_prelocking_list)
|
||||
{
|
||||
bool error= false;
|
||||
LEX *lex= thd->lex;
|
||||
|
||||
if (thd->locked_tables_mode <= LTM_LOCK_TABLES &&
|
||||
! has_prelocking_list && tables->updating &&
|
||||
tables->lock_type >= TL_WRITE_ALLOW_WRITE)
|
||||
{
|
||||
bool need_prelocking= FALSE;
|
||||
TABLE_LIST **save_query_tables_last= lex->query_tables_last;
|
||||
/*
|
||||
Extend statement's table list and the prelocking set with
|
||||
tables and routines according to the current prelocking
|
||||
strategy.
|
||||
|
||||
For example, for DML statements we need to add tables and routines
|
||||
used by triggers which are going to be invoked for this element of
|
||||
table list and also add tables required for handling of foreign keys.
|
||||
*/
|
||||
error= prelocking_strategy->handle_table(thd, lex, tables,
|
||||
&need_prelocking);
|
||||
|
||||
if (need_prelocking && ! lex->requires_prelocking())
|
||||
lex->mark_as_requiring_prelocking(save_query_tables_last);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Handle table list element by obtaining metadata lock, opening table or view
|
||||
@ -3949,14 +3988,13 @@ open_and_process_routine(THD *thd, Query_tables_list *prelocking_ctx,
|
||||
*/
|
||||
|
||||
static bool
|
||||
open_and_process_table(THD *thd, LEX *lex, TABLE_LIST *tables,
|
||||
uint *counter, uint flags,
|
||||
open_and_process_table(THD *thd, TABLE_LIST *tables, uint *counter, uint flags,
|
||||
Prelocking_strategy *prelocking_strategy,
|
||||
bool has_prelocking_list,
|
||||
Open_table_context *ot_ctx)
|
||||
bool has_prelocking_list, Open_table_context *ot_ctx)
|
||||
{
|
||||
bool error= FALSE;
|
||||
bool safe_to_ignore_table= FALSE;
|
||||
LEX *lex= thd->lex;
|
||||
DBUG_ENTER("open_and_process_table");
|
||||
DEBUG_SYNC(thd, "open_and_process_table");
|
||||
|
||||
@ -4175,38 +4213,9 @@ open_and_process_table(THD *thd, LEX *lex, TABLE_LIST *tables,
|
||||
if (tables->open_strategy && !tables->table)
|
||||
goto end;
|
||||
|
||||
/*
|
||||
If we are not already in prelocked mode and extended table list is not
|
||||
yet built we might have to build the prelocking set for this statement.
|
||||
|
||||
Since currently no prelocking strategy prescribes doing anything for
|
||||
tables which are only read, we do below checks only if table is going
|
||||
to be changed.
|
||||
*/
|
||||
if (thd->locked_tables_mode <= LTM_LOCK_TABLES &&
|
||||
! has_prelocking_list &&
|
||||
tables->lock_type >= TL_WRITE_ALLOW_WRITE)
|
||||
{
|
||||
bool need_prelocking= FALSE;
|
||||
TABLE_LIST **save_query_tables_last= lex->query_tables_last;
|
||||
/*
|
||||
Extend statement's table list and the prelocking set with
|
||||
tables and routines according to the current prelocking
|
||||
strategy.
|
||||
|
||||
For example, for DML statements we need to add tables and routines
|
||||
used by triggers which are going to be invoked for this element of
|
||||
table list and also add tables required for handling of foreign keys.
|
||||
*/
|
||||
error= prelocking_strategy->handle_table(thd, lex, tables,
|
||||
&need_prelocking);
|
||||
|
||||
if (need_prelocking && ! lex->requires_prelocking())
|
||||
lex->mark_as_requiring_prelocking(save_query_tables_last);
|
||||
|
||||
if (error)
|
||||
goto end;
|
||||
}
|
||||
error= extend_table_list(thd, tables, prelocking_strategy, has_prelocking_list);
|
||||
if (error)
|
||||
goto end;
|
||||
|
||||
/* Copy grant information from TABLE_LIST instance to TABLE one. */
|
||||
tables->table->grant= tables->grant;
|
||||
@ -4521,7 +4530,8 @@ open_tables_check_upgradable_mdl(THD *thd, TABLE_LIST *tables_start,
|
||||
*/
|
||||
|
||||
bool open_tables(THD *thd, const DDL_options_st &options,
|
||||
TABLE_LIST **start, uint *counter, uint flags,
|
||||
TABLE_LIST **start, uint *counter,
|
||||
Sroutine_hash_entry **sroutine_to_open_list, uint flags,
|
||||
Prelocking_strategy *prelocking_strategy)
|
||||
{
|
||||
/*
|
||||
@ -4564,7 +4574,7 @@ restart:
|
||||
|
||||
has_prelocking_list= thd->lex->requires_prelocking();
|
||||
table_to_open= start;
|
||||
sroutine_to_open= (Sroutine_hash_entry**) &thd->lex->sroutines_list.first;
|
||||
sroutine_to_open= sroutine_to_open_list;
|
||||
*counter= 0;
|
||||
THD_STAGE_INFO(thd, stage_opening_tables);
|
||||
|
||||
@ -4634,9 +4644,9 @@ restart:
|
||||
for (tables= *table_to_open; tables;
|
||||
table_to_open= &tables->next_global, tables= tables->next_global)
|
||||
{
|
||||
error= open_and_process_table(thd, thd->lex, tables, counter,
|
||||
flags, prelocking_strategy,
|
||||
has_prelocking_list, &ot_ctx);
|
||||
error= open_and_process_table(thd, tables, counter, flags,
|
||||
prelocking_strategy, has_prelocking_list,
|
||||
&ot_ctx);
|
||||
|
||||
if (error)
|
||||
{
|
||||
|
@ -251,8 +251,19 @@ lock_table_names(THD *thd, TABLE_LIST *table_list,
|
||||
table_list_end, lock_wait_timeout, flags);
|
||||
}
|
||||
bool open_tables(THD *thd, const DDL_options_st &options,
|
||||
TABLE_LIST **tables, uint *counter, uint flags,
|
||||
TABLE_LIST **tables, uint *counter,
|
||||
Sroutine_hash_entry **sroutine_to_open, uint flags,
|
||||
Prelocking_strategy *prelocking_strategy);
|
||||
|
||||
static inline bool
|
||||
open_tables(THD *thd, const DDL_options_st &options, TABLE_LIST **tables,
|
||||
uint *counter, uint flags, Prelocking_strategy *prelocking_strategy)
|
||||
{
|
||||
return open_tables(thd, options, tables, counter,
|
||||
&thd->lex->sroutines_list.first, flags,
|
||||
prelocking_strategy);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
open_tables(THD *thd, TABLE_LIST **tables, uint *counter, uint flags,
|
||||
Prelocking_strategy *prelocking_strategy)
|
||||
@ -547,6 +558,10 @@ inline bool open_and_lock_tables(THD *thd, TABLE_LIST *tables,
|
||||
|
||||
bool restart_trans_for_tables(THD *thd, TABLE_LIST *table);
|
||||
|
||||
bool extend_table_list(THD *thd, TABLE_LIST *tables,
|
||||
Prelocking_strategy *prelocking_strategy,
|
||||
bool has_prelocking_list);
|
||||
|
||||
/**
|
||||
A context of open_tables() function, used to recover
|
||||
from a failed open_table() or open_routine() attempt.
|
||||
|
@ -543,7 +543,7 @@ public:
|
||||
List<Index_hint> *hints= 0,
|
||||
List<String> *partition_names= 0,
|
||||
LEX_STRING *option= 0);
|
||||
virtual void set_lock_for_tables(thr_lock_type lock_type) {}
|
||||
virtual void set_lock_for_tables(thr_lock_type lock_type, bool for_update) {}
|
||||
|
||||
friend class st_select_lex_unit;
|
||||
friend bool mysql_new_select(LEX *lex, bool move_down);
|
||||
@ -963,7 +963,7 @@ public:
|
||||
TABLE_LIST *convert_right_join();
|
||||
List<Item>* get_item_list();
|
||||
ulong get_table_join_options();
|
||||
void set_lock_for_tables(thr_lock_type lock_type);
|
||||
void set_lock_for_tables(thr_lock_type lock_type, bool for_update);
|
||||
inline void init_order()
|
||||
{
|
||||
order_list.elements= 0;
|
||||
|
@ -2629,9 +2629,6 @@ mysql_execute_command(THD *thd)
|
||||
my_message(ER_SLAVE_IGNORED_TABLE, ER_THD(thd, ER_SLAVE_IGNORED_TABLE),
|
||||
MYF(0));
|
||||
}
|
||||
|
||||
for (table=all_tables; table; table=table->next_global)
|
||||
table->updating= TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -8002,9 +7999,8 @@ TABLE_LIST *st_select_lex::convert_right_join()
|
||||
query
|
||||
*/
|
||||
|
||||
void st_select_lex::set_lock_for_tables(thr_lock_type lock_type)
|
||||
void st_select_lex::set_lock_for_tables(thr_lock_type lock_type, bool for_update)
|
||||
{
|
||||
bool for_update= lock_type >= TL_READ_NO_INSERT;
|
||||
DBUG_ENTER("set_lock_for_tables");
|
||||
DBUG_PRINT("enter", ("lock_type: %d for_update: %d", lock_type,
|
||||
for_update));
|
||||
|
@ -7949,8 +7949,6 @@ int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list)
|
||||
table->alias_name_used= my_strcasecmp(table_alias_charset,
|
||||
table_list->schema_table_name,
|
||||
table_list->alias);
|
||||
table_list->table_name= table->s->table_name.str;
|
||||
table_list->table_name_length= table->s->table_name.length;
|
||||
table_list->table= table;
|
||||
table->next= thd->derived_tables;
|
||||
thd->derived_tables= table;
|
||||
|
@ -150,15 +150,11 @@ fk_truncate_illegal_if_parent(THD *thd, TABLE *table)
|
||||
/* Loop over the set of foreign keys for which this table is a parent. */
|
||||
while ((fk_info= it++))
|
||||
{
|
||||
DBUG_ASSERT(!my_strcasecmp(system_charset_info,
|
||||
fk_info->referenced_db->str,
|
||||
table->s->db.str));
|
||||
|
||||
DBUG_ASSERT(!my_strcasecmp(system_charset_info,
|
||||
fk_info->referenced_table->str,
|
||||
table->s->table_name.str));
|
||||
|
||||
if (my_strcasecmp(system_charset_info, fk_info->foreign_db->str,
|
||||
if (my_strcasecmp(system_charset_info, fk_info->referenced_db->str,
|
||||
table->s->db.str) ||
|
||||
my_strcasecmp(system_charset_info, fk_info->referenced_table->str,
|
||||
table->s->table_name.str) ||
|
||||
my_strcasecmp(system_charset_info, fk_info->foreign_db->str,
|
||||
table->s->db.str) ||
|
||||
my_strcasecmp(system_charset_info, fk_info->foreign_table->str,
|
||||
table->s->table_name.str))
|
||||
|
@ -1384,6 +1384,9 @@ int mysql_multi_update_prepare(THD *thd)
|
||||
List<Item> *fields= &lex->select_lex.item_list;
|
||||
table_map tables_for_update;
|
||||
bool update_view= 0;
|
||||
DML_prelocking_strategy prelocking_strategy;
|
||||
bool has_prelocking_list= thd->lex->requires_prelocking();
|
||||
|
||||
/*
|
||||
if this multi-update was converted from usual update, here is table
|
||||
counter else junk will be assigned here, but then replaced with real
|
||||
@ -1404,10 +1407,10 @@ int mysql_multi_update_prepare(THD *thd)
|
||||
keep prepare of multi-UPDATE compatible with concurrent LOCK TABLES WRITE
|
||||
and global read lock.
|
||||
*/
|
||||
if ((original_multiupdate &&
|
||||
open_tables(thd, &table_list, &table_count,
|
||||
(thd->stmt_arena->is_stmt_prepare() ?
|
||||
MYSQL_OPEN_FORCE_SHARED_MDL : 0))) ||
|
||||
if ((original_multiupdate && open_tables(thd, &table_list, &table_count,
|
||||
thd->stmt_arena->is_stmt_prepare()
|
||||
? MYSQL_OPEN_FORCE_SHARED_MDL : 0,
|
||||
&prelocking_strategy)) ||
|
||||
mysql_handle_derived(lex, DT_INIT))
|
||||
DBUG_RETURN(TRUE);
|
||||
/*
|
||||
@ -1454,6 +1457,9 @@ int mysql_multi_update_prepare(THD *thd)
|
||||
if (unsafe_key_update(lex->select_lex.leaf_tables, tables_for_update))
|
||||
DBUG_RETURN(true);
|
||||
|
||||
TABLE_LIST **new_tables= lex->query_tables_last;
|
||||
DBUG_ASSERT(*new_tables== NULL);
|
||||
|
||||
/*
|
||||
Setup timestamp handling and locking mode
|
||||
*/
|
||||
@ -1479,6 +1485,11 @@ int mysql_multi_update_prepare(THD *thd)
|
||||
If table will be updated we should not downgrade lock for it and
|
||||
leave it as is.
|
||||
*/
|
||||
tl->updating= 1;
|
||||
if (tl->belong_to_view)
|
||||
tl->belong_to_view->updating= 1;
|
||||
if (extend_table_list(thd, tl, &prelocking_strategy, has_prelocking_list))
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1501,7 +1512,6 @@ int mysql_multi_update_prepare(THD *thd)
|
||||
tl->lock_type= lock_type;
|
||||
else
|
||||
tl->set_lock_type(thd, lock_type);
|
||||
tl->updating= 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1510,6 +1520,20 @@ int mysql_multi_update_prepare(THD *thd)
|
||||
Note that unlike in the above loop we need to iterate here not only
|
||||
through all leaf tables but also through all view hierarchy.
|
||||
*/
|
||||
|
||||
uint addon_table_count= 0;
|
||||
if (*new_tables)
|
||||
{
|
||||
Sroutine_hash_entry **new_routines= thd->lex->sroutines_list.next;
|
||||
DBUG_ASSERT(*new_routines == NULL);
|
||||
if (open_tables(thd, thd->lex->create_info, new_tables,
|
||||
&addon_table_count, new_routines,
|
||||
thd->stmt_arena->is_stmt_prepare()
|
||||
? MYSQL_OPEN_FORCE_SHARED_MDL : 0,
|
||||
&prelocking_strategy))
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
||||
for (tl= table_list; tl; tl= tl->next_local)
|
||||
{
|
||||
bool not_used= false;
|
||||
@ -1538,7 +1562,7 @@ int mysql_multi_update_prepare(THD *thd)
|
||||
|
||||
/* now lock and fill tables */
|
||||
if (!thd->stmt_arena->is_stmt_prepare() &&
|
||||
lock_tables(thd, table_list, table_count, 0))
|
||||
lock_tables(thd, table_list, table_count + addon_table_count, 0))
|
||||
{
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
@ -435,7 +435,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
|
||||
*/
|
||||
if (lex->current_select->lock_type != TL_READ_DEFAULT)
|
||||
{
|
||||
lex->current_select->set_lock_for_tables(TL_READ_DEFAULT);
|
||||
lex->current_select->set_lock_for_tables(TL_READ_DEFAULT, false);
|
||||
view->mdl_request.set_type(MDL_EXCLUSIVE);
|
||||
}
|
||||
|
||||
@ -1528,6 +1528,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
|
||||
{
|
||||
tbl->lock_type= table->lock_type;
|
||||
tbl->mdl_request.set_type(table->mdl_request.type);
|
||||
tbl->updating= table->updating;
|
||||
}
|
||||
/*
|
||||
If the view is mergeable, we might want to
|
||||
|
@ -8399,7 +8399,7 @@ opt_select_lock_type:
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
lex->current_select->lock_type= TL_WRITE;
|
||||
lex->current_select->set_lock_for_tables(TL_WRITE);
|
||||
lex->current_select->set_lock_for_tables(TL_WRITE, false);
|
||||
lex->safe_to_cache_query=0;
|
||||
}
|
||||
| LOCK_SYM IN_SYM SHARE_SYM MODE_SYM
|
||||
@ -8407,7 +8407,7 @@ opt_select_lock_type:
|
||||
LEX *lex=Lex;
|
||||
lex->current_select->lock_type= TL_READ_WITH_SHARED_LOCKS;
|
||||
lex->current_select->
|
||||
set_lock_for_tables(TL_READ_WITH_SHARED_LOCKS);
|
||||
set_lock_for_tables(TL_READ_WITH_SHARED_LOCKS, false);
|
||||
lex->safe_to_cache_query=0;
|
||||
}
|
||||
;
|
||||
@ -11781,7 +11781,7 @@ insert:
|
||||
insert_lock_option
|
||||
opt_ignore insert2
|
||||
{
|
||||
Select->set_lock_for_tables($3);
|
||||
Select->set_lock_for_tables($3, true);
|
||||
Lex->current_select= &Lex->select_lex;
|
||||
}
|
||||
insert_field_spec opt_insert_update
|
||||
@ -11798,7 +11798,7 @@ replace:
|
||||
}
|
||||
replace_lock_option insert2
|
||||
{
|
||||
Select->set_lock_for_tables($3);
|
||||
Select->set_lock_for_tables($3, true);
|
||||
Lex->current_select= &Lex->select_lex;
|
||||
}
|
||||
insert_field_spec
|
||||
@ -11975,14 +11975,14 @@ update:
|
||||
opt_low_priority opt_ignore join_table_list
|
||||
SET update_list
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
if (lex->select_lex.table_list.elements > 1)
|
||||
lex->sql_command= SQLCOM_UPDATE_MULTI;
|
||||
else if (lex->select_lex.get_table_list()->derived)
|
||||
SELECT_LEX *slex= &Lex->select_lex;
|
||||
if (slex->table_list.elements > 1)
|
||||
Lex->sql_command= SQLCOM_UPDATE_MULTI;
|
||||
else if (slex->get_table_list()->derived)
|
||||
{
|
||||
/* it is single table update and it is update of derived table */
|
||||
my_error(ER_NON_UPDATABLE_TABLE, MYF(0),
|
||||
lex->select_lex.get_table_list()->alias, "UPDATE");
|
||||
slex->get_table_list()->alias, "UPDATE");
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
/*
|
||||
@ -11990,7 +11990,7 @@ update:
|
||||
be too pessimistic. We will decrease lock level if possible in
|
||||
mysql_multi_update().
|
||||
*/
|
||||
Select->set_lock_for_tables($3);
|
||||
slex->set_lock_for_tables($3, slex->table_list.elements == 1);
|
||||
}
|
||||
opt_where_clause opt_order_clause delete_limit_clause {}
|
||||
;
|
||||
@ -14851,13 +14851,16 @@ table_lock:
|
||||
table_ident opt_table_alias lock_option
|
||||
{
|
||||
thr_lock_type lock_type= (thr_lock_type) $3;
|
||||
bool lock_for_write= (lock_type >= TL_WRITE_ALLOW_WRITE);
|
||||
if (!Select->add_table_to_list(thd, $1, $2, 0, lock_type,
|
||||
(lock_for_write ?
|
||||
lock_type == TL_WRITE_CONCURRENT_INSERT ?
|
||||
MDL_SHARED_WRITE :
|
||||
MDL_SHARED_NO_READ_WRITE :
|
||||
MDL_SHARED_READ)))
|
||||
bool lock_for_write= lock_type >= TL_WRITE_ALLOW_WRITE;
|
||||
ulong table_options= lock_for_write ? TL_OPTION_UPDATING : 0;
|
||||
enum_mdl_type mdl_type= !lock_for_write
|
||||
? MDL_SHARED_READ
|
||||
: lock_type == TL_WRITE_CONCURRENT_INSERT
|
||||
? MDL_SHARED_WRITE
|
||||
: MDL_SHARED_NO_READ_WRITE;
|
||||
|
||||
if (!Select->add_table_to_list(thd, $1, $2, table_options,
|
||||
lock_type, mdl_type))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
;
|
||||
|
@ -5553,7 +5553,8 @@ const char *Field_iterator_table_ref::get_table_name()
|
||||
return natural_join_it.column_ref()->table_name();
|
||||
|
||||
DBUG_ASSERT(!strcmp(table_ref->table_name,
|
||||
table_ref->table->s->table_name.str));
|
||||
table_ref->table->s->table_name.str) ||
|
||||
table_ref->schema_table);
|
||||
return table_ref->table_name;
|
||||
}
|
||||
|
||||
|
@ -1789,6 +1789,7 @@ struct TABLE_LIST
|
||||
table_name_length= table_name_length_arg;
|
||||
alias= (char*) (alias_arg ? alias_arg : table_name_arg);
|
||||
lock_type= lock_type_arg;
|
||||
updating= lock_type >= TL_WRITE_ALLOW_WRITE;
|
||||
mdl_request.init(MDL_key::TABLE, db, table_name, mdl_type, MDL_TRANSACTION);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user