summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2019-04-26 14:02:37 +0200
committerSergei Golubchik <serg@mariadb.org>2019-04-26 14:02:37 +0200
commit2ce52790ffc72c4a4d3670ebf67c6655450620f2 (patch)
tree4be382f34905809f0a19e87574e2b07b91f5cb7c /sql
parentcaa9023c9ed101acbcf6b9bd821a09daeb8271ee (diff)
parent757daa4174ed1b8786d0307852f79885dd08ea89 (diff)
downloadmariadb-git-2ce52790ffc72c4a4d3670ebf67c6655450620f2.tar.gz
Merge branch '5.5' into 10.1
Diffstat (limited to 'sql')
-rw-r--r--sql/log_event.cc25
-rw-r--r--sql/log_event_old.cc19
-rw-r--r--sql/sql_acl.cc10
-rw-r--r--sql/sql_base.cc92
-rw-r--r--sql/sql_base.h17
-rw-r--r--sql/sql_lex.h4
-rw-r--r--sql/sql_parse.cc6
-rw-r--r--sql/sql_show.cc2
-rw-r--r--sql/sql_truncate.cc14
-rw-r--r--sql/sql_update.cc36
-rw-r--r--sql/sql_view.cc3
-rw-r--r--sql/sql_yacc.yy37
-rw-r--r--sql/table.cc3
-rw-r--r--sql/table.h1
14 files changed, 162 insertions, 107 deletions
diff --git a/sql/log_event.cc b/sql/log_event.cc
index bb373a4ed84..a6091fcc28d 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -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;
}
diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc
index a6f2ed3f416..f0c1c61bb1d 100644
--- a/sql/log_event_old.cc
+++ b/sql/log_event_old.cc
@@ -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);
}
/*
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index c2e5bfd8c11..83526532bdd 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -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)
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 733a3a1f3ed..3a7ffdb656a 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -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)
{
diff --git a/sql/sql_base.h b/sql/sql_base.h
index 94294e3aa43..53b5885460b 100644
--- a/sql/sql_base.h
+++ b/sql/sql_base.h
@@ -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.
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 0142f812632..845e1242eb7 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -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;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 6649c60f827..3f9d9190d76 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -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));
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 46914ea14c4..7f0c50a2e55 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -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;
diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc
index 57cb6df55ca..6252caf98b0 100644
--- a/sql/sql_truncate.cc
+++ b/sql/sql_truncate.cc
@@ -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))
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 78aa059f64f..721e1ed908c 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -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);
}
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 4d7c3de9337..cef20ba08f9 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -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
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 5111f0690ab..ca30bc202cf 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -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;
}
;
diff --git a/sql/table.cc b/sql/table.cc
index 31f0d255847..8373f6735dc 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -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;
}
diff --git a/sql/table.h b/sql/table.h
index afe3220c943..e7d3c95713e 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -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);
}