Merge branch '5.5' into 10.1

This commit is contained in:
Sergei Golubchik 2019-04-26 14:02:37 +02:00
commit 2ce52790ff
29 changed files with 357 additions and 108 deletions

View File

@ -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

View File

@ -0,0 +1,4 @@
PREPARE stmt2 FROM "CREATE VIEW v AS SELECT * FROM INFORMATION_SCHEMA.TABLES";
FLUSH PRIVILEGES;
EXECUTE stmt2;
DROP VIEW v;

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View 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

View 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;

View File

@ -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

View 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;

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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);
}
/*

View File

@ -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)

View File

@ -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)
{

View File

@ -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.

View File

@ -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;

View File

@ -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));

View File

@ -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;

View File

@ -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))

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}
;

View File

@ -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;
}

View File

@ -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);
}