summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorOleksandr Byelkin <sanja@mariadb.com>2019-05-04 17:04:55 +0200
committerOleksandr Byelkin <sanja@mariadb.com>2019-05-04 17:04:55 +0200
commit8cbb14ef5d180687f131bc44a4e8fc84083d033c (patch)
tree091f11e2d20f95656a7b12294782eb0488fd4fcc /sql
parent4345868382ca3525de5eb432302b6b9b957b47c1 (diff)
parentb85aa20065504bdda4bc03c2bd7eb7de38865c5d (diff)
downloadmariadb-git-8cbb14ef5d180687f131bc44a4e8fc84083d033c.tar.gz
Merge branch '10.1' into 10.2
Diffstat (limited to 'sql')
-rw-r--r--sql/events.cc6
-rw-r--r--sql/field.cc2
-rw-r--r--sql/gen_win_tzname_data.ps111
-rw-r--r--sql/ha_partition.cc11
-rw-r--r--sql/handler.h5
-rw-r--r--sql/item_func.cc6
-rw-r--r--sql/item_sum.cc93
-rw-r--r--sql/item_sum.h9
-rw-r--r--sql/log_event.cc23
-rw-r--r--sql/log_event_old.cc19
-rw-r--r--sql/mysqld.cc48
-rw-r--r--sql/share/errmsg-utf8.txt4
-rw-r--r--sql/sql_acl.cc33
-rw-r--r--sql/sql_base.cc95
-rw-r--r--sql/sql_base.h17
-rw-r--r--sql/sql_class.cc1
-rw-r--r--sql/sql_class.h1
-rw-r--r--sql/sql_db.cc20
-rw-r--r--sql/sql_db.h2
-rw-r--r--sql/sql_lex.h4
-rw-r--r--sql/sql_parse.cc16
-rw-r--r--sql/sql_select.cc18
-rw-r--r--sql/sql_show.cc10
-rw-r--r--sql/sql_statistics.cc20
-rw-r--r--sql/sql_string.cc21
-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
-rw-r--r--sql/win_tzname_data.h136
32 files changed, 555 insertions, 170 deletions
diff --git a/sql/events.cc b/sql/events.cc
index cd0257f5317..70ee0c2631f 100644
--- a/sql/events.cc
+++ b/sql/events.cc
@@ -417,6 +417,12 @@ Events::create_event(THD *thd, Event_parse_data *parse_data)
thd->restore_stmt_binlog_format(save_binlog_format);
+ if (!ret && Events::opt_event_scheduler == Events::EVENTS_OFF)
+ {
+ push_warning(thd, Sql_condition::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
+ "Event scheduler is switched off, use SET GLOBAL event_scheduler=ON to enable it.");
+ }
+
DBUG_RETURN(ret);
WSREP_ERROR_LABEL:
diff --git a/sql/field.cc b/sql/field.cc
index 0621015c0e4..30eed286512 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -2428,7 +2428,7 @@ int Field::set_default()
/* Copy constant value stored in s->default_values */
my_ptrdiff_t l_offset= (my_ptrdiff_t) (table->s->default_values -
table->record[0]);
- memcpy(ptr, ptr + l_offset, pack_length());
+ memcpy(ptr, ptr + l_offset, pack_length_in_rec());
if (maybe_null_in_table())
*null_ptr= ((*null_ptr & (uchar) ~null_bit) |
(null_ptr[l_offset] & null_bit));
diff --git a/sql/gen_win_tzname_data.ps1 b/sql/gen_win_tzname_data.ps1
new file mode 100644
index 00000000000..13b6ce6ffd0
--- /dev/null
+++ b/sql/gen_win_tzname_data.ps1
@@ -0,0 +1,11 @@
+# Generates a header file for converting between Windows timezone names to tzdb names
+# using CLDR data.
+# Usage: powershell -File gen_win_tzname_data.ps1 > win_tzname_data.h
+
+write-output "/* This file was generated using gen_win_tzname_data.ps1 */"
+$xdoc = new-object System.Xml.XmlDocument
+$xdoc.load("https://unicode.org/repos/cldr/trunk/common/supplemental/windowsZones.xml")
+$nodes = $xdoc.SelectNodes("//mapZone[@territory='001']") # use default territory (001)
+foreach ($node in $nodes) {
+ write-output ('{L"'+ $node.other + '","'+ $node.type+'"},')
+}
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 8700610415c..c280bc13e0a 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -1,6 +1,6 @@
/*
- Copyright (c) 2005, 2017, Oracle and/or its affiliates.
- Copyright (c) 2009, 2018, MariaDB
+ Copyright (c) 2005, 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
@@ -8375,7 +8375,12 @@ bool ha_partition::inplace_alter_table(TABLE *altered_table,
for (index= 0; index < m_tot_parts && !error; index++)
{
- ha_alter_info->handler_ctx= part_inplace_ctx->handler_ctx_array[index];
+ if ((ha_alter_info->handler_ctx=
+ part_inplace_ctx->handler_ctx_array[index]) != NULL
+ && index != 0)
+ ha_alter_info->handler_ctx->set_shared_data
+ (*part_inplace_ctx->handler_ctx_array[index - 1]);
+
if (m_file[index]->ha_inplace_alter_table(altered_table,
ha_alter_info))
error= true;
diff --git a/sql/handler.h b/sql/handler.h
index 848c9956868..d1e9f93797b 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -1,8 +1,8 @@
#ifndef HANDLER_INCLUDED
#define HANDLER_INCLUDED
/*
- Copyright (c) 2000, 2016, 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
@@ -1834,6 +1834,7 @@ public:
inplace_alter_handler_ctx() {}
virtual ~inplace_alter_handler_ctx() {}
+ virtual void set_shared_data(const inplace_alter_handler_ctx& ctx) {}
};
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 33f0b982445..0fa941319a6 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -2765,6 +2765,7 @@ bool Item_func_min_max::fix_length_and_dec()
switch (tmp_cmp_type) {
case TIME_RESULT:
+ {
// At least one temporal argument was found.
if (temporal_type_count < arg_count)
maybe_null= true; // Non-temporal-to-temporal conversion can return NULL
@@ -2774,8 +2775,11 @@ bool Item_func_min_max::fix_length_and_dec()
set_if_smaller(decimals, TIME_SECOND_PART_DIGITS);
else
decimals= 0;
+ uint len= decimals ? (decimals + 1) : 0;
+ len+= mysql_temporal_int_part_length(temporal_field_type);
+ fix_char_length(len);
break;
-
+ }
case STRING_RESULT:
/*
All arguments are of string-alike types:
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 4405477b6a1..b1b22d0877f 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -3319,6 +3319,7 @@ Item_func_group_concat::Item_func_group_concat(THD *thd,
tmp_table_param(item->tmp_table_param),
separator(item->separator),
tree(item->tree),
+ tree_len(item->tree_len),
unique_filter(item->unique_filter),
table(item->table),
context(item->context),
@@ -3443,7 +3444,10 @@ void Item_func_group_concat::clear()
warning_for_row= FALSE;
no_appended= TRUE;
if (tree)
+ {
reset_tree(tree);
+ tree_len= 0;
+ }
if (unique_filter)
unique_filter->reset();
if (table && table->blob_storage)
@@ -3451,6 +3455,62 @@ void Item_func_group_concat::clear()
/* No need to reset the table as we never call write_row */
}
+struct st_repack_tree {
+ TREE tree;
+ TABLE *table;
+ size_t len, maxlen;
+};
+
+extern "C"
+int copy_to_tree(void* key, element_count count __attribute__((unused)),
+ void* arg)
+{
+ struct st_repack_tree *st= (struct st_repack_tree*)arg;
+ TABLE *table= st->table;
+ Field* field= table->field[0];
+ const uchar *ptr= field->ptr_in_record((uchar*)key - table->s->null_bytes);
+ size_t len= (size_t)field->val_int(ptr);
+
+ DBUG_ASSERT(count == 1);
+ if (!tree_insert(&st->tree, key, 0, st->tree.custom_arg))
+ return 1;
+
+ st->len += len;
+ return st->len > st->maxlen;
+}
+
+bool Item_func_group_concat::repack_tree(THD *thd)
+{
+ struct st_repack_tree st;
+
+ init_tree(&st.tree, (size_t) MY_MIN(thd->variables.max_heap_table_size,
+ thd->variables.sortbuff_size/16), 0,
+ tree->size_of_element, group_concat_key_cmp_with_order, NULL,
+ (void*) this, MYF(MY_THREAD_SPECIFIC));
+ st.table= table;
+ st.len= 0;
+ st.maxlen= (size_t)thd->variables.group_concat_max_len;
+ tree_walk(tree, &copy_to_tree, &st, left_root_right);
+ if (st.len <= st.maxlen) // Copying aborted. Must be OOM
+ {
+ delete_tree(&st.tree);
+ return 1;
+ }
+ delete_tree(tree);
+ *tree= st.tree;
+ tree_len= st.len;
+ return 0;
+}
+
+/*
+ Repacking the tree is expensive. But it keeps the tree small, and
+ inserting into an unnecessary large tree is also waste of time.
+
+ The following number is best-by-test. Test execution time slowly
+ decreases up to N=10 (that is, factor=1024) and then starts to increase,
+ again, very slowly.
+*/
+#define GCONCAT_REPACK_FACTOR (1 << 10)
bool Item_func_group_concat::add()
{
@@ -3460,6 +3520,9 @@ bool Item_func_group_concat::add()
if (copy_funcs(tmp_table_param->items_to_copy, table->in_use))
return TRUE;
+ size_t row_str_len= 0;
+ StringBuffer<MAX_FIELD_WIDTH> buf;
+ String *res;
for (uint i= 0; i < arg_count_field; i++)
{
Item *show_item= args[i];
@@ -3467,8 +3530,13 @@ bool Item_func_group_concat::add()
continue;
Field *field= show_item->get_tmp_table_field();
- if (field && field->is_null_in_record((const uchar*) table->record[0]))
- return 0; // Skip row if it contains null
+ if (field)
+ {
+ if (field->is_null_in_record((const uchar*) table->record[0]))
+ return 0; // Skip row if it contains null
+ if (tree && (res= field->val_str(&buf)))
+ row_str_len+= res->length();
+ }
}
null_value= FALSE;
@@ -3486,11 +3554,18 @@ bool Item_func_group_concat::add()
TREE_ELEMENT *el= 0; // Only for safety
if (row_eligible && tree)
{
+ THD *thd= table->in_use;
+ table->field[0]->store(row_str_len, FALSE);
+ if (tree_len > thd->variables.group_concat_max_len * GCONCAT_REPACK_FACTOR
+ && tree->elements_in_tree > 1)
+ if (repack_tree(thd))
+ return 1;
el= tree_insert(tree, table->record[0] + table->s->null_bytes, 0,
tree->custom_arg);
/* check if there was enough memory to insert the row */
if (!el)
return 1;
+ tree_len+= row_str_len;
}
/*
If the row is not a duplicate (el->count == 1)
@@ -3623,10 +3698,19 @@ bool Item_func_group_concat::setup(THD *thd)
if (setup_order(thd, Ref_ptr_array(ref_pointer_array, n_elems),
context->table_list, list, all_fields, *order))
DBUG_RETURN(TRUE);
+ /*
+ Prepend the field to store the length of the string representation
+ of this row. Used to detect when the tree goes over group_concat_max_len
+ */
+ Item *item= new (thd->mem_root)
+ Item_uint(thd, thd->variables.group_concat_max_len);
+ if (!item || all_fields.push_front(item, thd->mem_root))
+ DBUG_RETURN(TRUE);
}
count_field_types(select_lex, tmp_table_param, all_fields, 0);
tmp_table_param->force_copy_fields= force_copy_fields;
+ tmp_table_param->hidden_field_count= (arg_count_order > 0);
DBUG_ASSERT(table == 0);
if (order_or_distinct)
{
@@ -3686,10 +3770,11 @@ bool Item_func_group_concat::setup(THD *thd)
create this tree.
*/
init_tree(tree, (size_t)MY_MIN(thd->variables.max_heap_table_size,
- thd->variables.sortbuff_size/16), 0,
- tree_key_length,
+ thd->variables.sortbuff_size/16), 0,
+ tree_key_length,
group_concat_key_cmp_with_order, NULL, (void*) this,
MYF(MY_THREAD_SPECIFIC));
+ tree_len= 0;
}
if (distinct)
diff --git a/sql/item_sum.h b/sql/item_sum.h
index 5c8ff520259..c1373f6c1fc 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -1593,6 +1593,7 @@ class Item_func_group_concat : public Item_sum
String *separator;
TREE tree_base;
TREE *tree;
+ size_t tree_len;
Item **ref_pointer_array;
/**
@@ -1630,7 +1631,9 @@ class Item_func_group_concat : public Item_sum
element_count count __attribute__((unused)),
void* item_arg);
protected:
- virtual Field *make_string_field(TABLE *table);
+ Field *make_string_field(TABLE *table);
+
+ bool repack_tree(THD *thd);
public:
Item_func_group_concat(THD *thd, Name_resolution_context *context_arg,
@@ -1686,8 +1689,8 @@ public:
String* val_str(String* str);
Item *copy_or_same(THD* thd);
void no_rows_in_result() {}
- virtual void print(String *str, enum_query_type query_type);
- virtual bool change_context_processor(void *cntx)
+ void print(String *str, enum_query_type query_type);
+ bool change_context_processor(void *cntx)
{ context= (Name_resolution_context *)cntx; return FALSE; }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_group_concat>(thd, mem_root, this); }
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 7ebc75dd1bf..8aea32004c3 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2000, 2018, Oracle and/or its affiliates.
+ 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
@@ -39,6 +39,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"
@@ -10777,6 +10778,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;
@@ -10801,7 +10808,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))
{
@@ -10814,23 +10820,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 2b6509048ba..098672947b3 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/mysqld.cc b/sql/mysqld.cc
index 2d872afaeb8..cf96318f34c 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -4118,6 +4118,39 @@ static int init_early_variables()
return 0;
}
+#ifdef _WIN32
+static void get_win_tzname(char* buf, size_t size)
+{
+ static struct
+ {
+ const wchar_t* windows_name;
+ const char* tzdb_name;
+ }
+ tz_data[] =
+ {
+#include "win_tzname_data.h"
+ {0,0}
+ };
+ DYNAMIC_TIME_ZONE_INFORMATION tzinfo;
+ if (GetDynamicTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_UNKNOWN)
+ {
+ strncpy(buf, "unknown", size);
+ return;
+ }
+
+ for (size_t i= 0; tz_data[i].windows_name; i++)
+ {
+ if (wcscmp(tzinfo.TimeZoneKeyName, tz_data[i].windows_name) == 0)
+ {
+ strncpy(buf, tz_data[i].tzdb_name, size);
+ return;
+ }
+ }
+ wcstombs(buf, tzinfo.TimeZoneKeyName, size);
+ buf[size-1]= 0;
+ return;
+}
+#endif
static int init_common_variables()
{
@@ -4163,22 +4196,13 @@ static int init_common_variables()
if (ignore_db_dirs_init())
exit(1);
-#ifdef HAVE_TZNAME
+#ifdef _WIN32
+ get_win_tzname(system_time_zone, sizeof(system_time_zone));
+#elif defined(HAVE_TZNAME)
struct tm tm_tmp;
localtime_r(&server_start_time,&tm_tmp);
const char *tz_name= tzname[tm_tmp.tm_isdst != 0 ? 1 : 0];
-#ifdef _WIN32
- /*
- Time zone name may be localized and contain non-ASCII characters,
- Convert from ANSI encoding to UTF8.
- */
- wchar_t wtz_name[sizeof(system_time_zone)];
- mbstowcs(wtz_name, tz_name, sizeof(system_time_zone)-1);
- WideCharToMultiByte(CP_UTF8,0, wtz_name, -1, system_time_zone,
- sizeof(system_time_zone) - 1, NULL, NULL);
-#else
strmake_buf(system_time_zone, tz_name);
-#endif /* _WIN32 */
#endif /* HAVE_TZNAME */
/*
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index 60f1253dd63..1c828db65a8 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -6134,8 +6134,8 @@ ER_EVENT_RECURSION_FORBIDDEN
eng "Recursion of EVENT DDL statements is forbidden when body is present"
ger "Rekursivität von EVENT-DDL-Anweisungen ist unzulässig wenn ein Hauptteil (Body) existiert"
ER_EVENTS_DB_ERROR
- eng "Cannot proceed because system tables used by Event Scheduler were found damaged at server start"
- ger "Kann nicht weitermachen, weil die Tabellen, die von Events verwendet werden, beim Serverstart als beschädigt markiert wurden"
+ eng "Cannot proceed, because event scheduler is disabled"
+ ger "Die Operation kann nicht fortgesetzt werden, da Event Scheduler deaktiviert ist."
ER_ONLY_INTEGERS_ALLOWED
eng "Only integers allowed as number here"
ger "An dieser Stelle sind nur Ganzzahlen zulässig"
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 871744c6b36..d5ef3c38b7b 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -861,8 +861,7 @@ class Grant_table_base
void init(enum thr_lock_type lock_type, bool is_optional)
{
tl.open_type= OT_BASE_ONLY;
- if (lock_type >= TL_WRITE_ALLOW_WRITE)
- tl.updating= 1;
+ tl.i_s_requested_object= OPEN_TABLE_ONLY;
if (is_optional)
tl.open_strategy= TABLE_LIST::OPEN_IF_EXISTS;
}
@@ -1875,6 +1874,12 @@ static bool acl_load(THD *thd, const Grant_tables& tables)
if (user_table.init_read_record(&read_record_info, thd))
DBUG_RETURN(true);
+ if (user_table.num_fields() < 13) // number of columns in 3.21
+ {
+ sql_print_error("Fatal error: mysql.user table is damaged or in "
+ "unsupported 3.20 format.");
+ DBUG_RETURN(true);
+ }
username_char_length= MY_MIN(user_table.user()->char_length(),
USERNAME_CHAR_LENGTH);
if (user_table.password()) // Password column might be missing. (MySQL 5.7.6+)
@@ -12041,7 +12046,7 @@ struct MPVIO_EXT :public MYSQL_PLUGIN_VIO
};
/**
- a helper function to report an access denied error in all the proper places
+ a helper function to report an access denied error in most proper places
*/
static void login_failed_error(THD *thd)
{
@@ -13475,10 +13480,26 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len)
/* Change a database if necessary */
if (mpvio.db.length)
{
- if (mysql_change_db(thd, &mpvio.db, FALSE))
+ uint err = mysql_change_db(thd, &mpvio.db, FALSE);
+ if(err)
{
- /* mysql_change_db() has pushed the error message. */
- status_var_increment(thd->status_var.access_denied_errors);
+ if (err == ER_DBACCESS_DENIED_ERROR)
+ {
+ /*
+ Got an "access denied" error, which must be handled
+ other access denied errors (see login_failed_error()).
+ mysql_change_db() already sent error to client, and
+ wrote to general log, we only need to increment the counter
+ and maybe write a warning to error log.
+ */
+ status_var_increment(thd->status_var.access_denied_errors);
+ if (global_system_variables.log_warnings > 1)
+ {
+ Security_context* sctx = thd->security_ctx;
+ sql_print_warning(ER_THD(thd, err),
+ sctx->priv_user, sctx->priv_host, mpvio.db.str);
+ }
+ }
DBUG_RETURN(1);
}
}
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index e0a907abfb3..dc4c390a719 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -3257,6 +3257,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
@@ -3283,14 +3322,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");
@@ -3563,38 +3601,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;
@@ -3917,7 +3926,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)
{
/*
@@ -3960,7 +3970,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);
@@ -4030,9 +4040,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)
{
@@ -8391,8 +8401,7 @@ my_bool mysql_rm_tmp_tables(void)
{
file=dirp->dir_entry+idx;
- if (!memcmp(file->name, tmp_file_prefix,
- tmp_file_prefix_length))
+ if (!strncmp(file->name, tmp_file_prefix, tmp_file_prefix_length))
{
char *ext= fn_ext(file->name);
uint ext_len= strlen(ext);
diff --git a/sql/sql_base.h b/sql/sql_base.h
index 37cc9e8e8f1..46520f6d83f 100644
--- a/sql/sql_base.h
+++ b/sql/sql_base.h
@@ -238,8 +238,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)
@@ -509,6 +520,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_class.cc b/sql/sql_class.cc
index 1c29e3d18a7..142088faea4 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -840,6 +840,7 @@ THD::THD(my_thread_id id, bool is_wsrep_applier)
memset(&invoker_host, 0, sizeof(invoker_host));
prepare_derived_at_open= FALSE;
create_tmp_table_for_derived= FALSE;
+ force_read_stats= FALSE;
save_prep_leaf_list= FALSE;
org_charset= 0;
/* Restore THR_THD */
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 38e55f9c4a9..9c968abf25c 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -38,6 +38,7 @@
#include "thr_lock.h" /* thr_lock_type, THR_LOCK_DATA, THR_LOCK_INFO */
#include "thr_timer.h"
#include "thr_malloc.h"
+#include <my_tree.h>
#include "sql_digest_stream.h" // sql_digest_state
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 0e554e29380..ebc04decbb3 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -1459,12 +1459,12 @@ static void backup_current_db_name(THD *thd,
a stack pointer set by Stored Procedures was used by replication after
the stack address was long gone.
- @return Operation status
- @retval FALSE Success
- @retval TRUE Error
+ @return error code (ER_XXX)
+ @retval 0 Success
+ @retval >0 Error
*/
-bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch)
+uint mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch)
{
LEX_STRING new_db_file_name;
@@ -1494,7 +1494,7 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch)
{
my_message(ER_NO_DB_ERROR, ER_THD(thd, ER_NO_DB_ERROR), MYF(0));
- DBUG_RETURN(TRUE);
+ DBUG_RETURN(ER_NO_DB_ERROR);
}
}
DBUG_PRINT("enter",("name: '%s'", new_db_name->str));
@@ -1520,7 +1520,7 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch)
new_db_file_name.length= new_db_name->length;
if (new_db_file_name.str == NULL)
- DBUG_RETURN(TRUE); /* the error is set */
+ DBUG_RETURN(ER_OUT_OF_RESOURCES); /* the error is set */
/*
NOTE: if check_db_name() fails, we should throw an error in any case,
@@ -1539,7 +1539,7 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch)
if (force_switch)
mysql_change_db_impl(thd, NULL, 0, thd->variables.collation_server);
- DBUG_RETURN(TRUE);
+ DBUG_RETURN(ER_WRONG_DB_NAME);
}
DBUG_PRINT("info",("Use database: %s", new_db_file_name.str));
@@ -1569,7 +1569,7 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch)
general_log_print(thd, COM_INIT_DB, ER_THD(thd, ER_DBACCESS_DENIED_ERROR),
sctx->priv_user, sctx->priv_host, new_db_file_name.str);
my_free(new_db_file_name.str);
- DBUG_RETURN(TRUE);
+ DBUG_RETURN(ER_DBACCESS_DENIED_ERROR);
}
#endif
@@ -1603,7 +1603,7 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch)
/* The operation failed. */
- DBUG_RETURN(TRUE);
+ DBUG_RETURN(ER_BAD_DB_ERROR);
}
}
@@ -1619,7 +1619,7 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch)
done:
SESSION_TRACKER_CHANGED(thd, CURRENT_SCHEMA_TRACKER, NULL);
SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
- DBUG_RETURN(FALSE);
+ DBUG_RETURN(0);
}
diff --git a/sql/sql_db.h b/sql/sql_db.h
index ed8417a7793..b778e42645a 100644
--- a/sql/sql_db.h
+++ b/sql/sql_db.h
@@ -26,7 +26,7 @@ bool mysql_alter_db(THD *thd, const char *db,
const Schema_specification_st *create);
bool mysql_rm_db(THD *thd, char *db, bool if_exists);
bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db);
-bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name,
+uint mysql_change_db(THD *thd, const LEX_STRING *new_db_name,
bool force_switch);
bool mysql_opt_change_db(THD *thd,
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 2af1d527cd3..a880b6e4283 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -547,7 +547,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) {}
void set_slave(st_select_lex_node *slave_arg) { slave= slave_arg; }
void move_node(st_select_lex_node *where_to_move)
{
@@ -1026,7 +1026,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 68a08dc2b3f..4a4fc91296a 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -3124,9 +3124,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;
}
/*
@@ -4310,6 +4307,16 @@ end_with_restore_list:
else
res= 0;
+ /*
+ We can not use mysql_explain_union() because of parameters of
+ mysql_select in mysql_multi_update so just set the option if needed
+ */
+ if (thd->lex->describe)
+ {
+ select_lex->set_explain_type(FALSE);
+ select_lex->options|= SELECT_DESCRIBE;
+ }
+
res= mysql_multi_update_prepare(thd);
#ifdef HAVE_REPLICATION
@@ -8590,9 +8597,8 @@ bool st_select_lex::add_window_spec(THD *thd,
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_select.cc b/sql/sql_select.cc
index bcbe4597aff..5e0472b4224 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -16473,28 +16473,28 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
/* Fall through */
case Item::COND_ITEM:
+ case Item::SUBSELECT_ITEM:
+ case Item::REF_ITEM:
+ case Item::EXPR_CACHE_ITEM:
+ if (make_copy_field)
+ {
+ DBUG_ASSERT(((Item_result_field*)item)->result_field);
+ *from_field= ((Item_result_field*)item)->result_field;
+ }
+ /* Fall through */
case Item::FIELD_AVG_ITEM:
case Item::FIELD_STD_ITEM:
- case Item::SUBSELECT_ITEM:
- /* The following can only happen with 'CREATE TABLE ... SELECT' */
case Item::PROC_ITEM:
case Item::INT_ITEM:
case Item::REAL_ITEM:
case Item::DECIMAL_ITEM:
case Item::STRING_ITEM:
case Item::DATE_ITEM:
- case Item::REF_ITEM:
case Item::NULL_ITEM:
case Item::VARBIN_ITEM:
case Item::CACHE_ITEM:
case Item::WINDOW_FUNC_ITEM: // psergey-winfunc:
- case Item::EXPR_CACHE_ITEM:
case Item::PARAM_ITEM:
- if (make_copy_field)
- {
- DBUG_ASSERT(((Item_result_field*)item)->result_field);
- *from_field= ((Item_result_field*)item)->result_field;
- }
return create_tmp_field_from_item(thd, item, table,
(make_copy_field ? 0 : copy_func),
modify_item);
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index c84ac5f4977..56103d8b654 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -4398,8 +4398,8 @@ fill_schema_table_by_open(THD *thd, bool is_show_fields_or_keys,
SQLCOM_SHOW_FIELDS is used because it satisfies
'only_view_structure()'.
*/
- lex->sql_command= SQLCOM_SHOW_FIELDS;
thd->force_read_stats= get_schema_table_idx(schema_table) == SCH_STATISTICS;
+ lex->sql_command= SQLCOM_SHOW_FIELDS;
result= (thd->open_temporary_tables(table_list) ||
open_normal_and_derived_tables(thd, table_list,
(MYSQL_OPEN_IGNORE_FLUSH |
@@ -4408,15 +4408,15 @@ fill_schema_table_by_open(THD *thd, bool is_show_fields_or_keys,
MYSQL_OPEN_FAIL_ON_MDL_CONFLICT : 0)),
DT_INIT | DT_PREPARE | DT_CREATE));
- (void) read_statistics_for_tables_if_needed(thd, table_list);
- thd->force_read_stats= false;
-
/*
Restore old value of sql_command back as it is being looked at in
process_table() function.
*/
lex->sql_command= old_lex->sql_command;
+ (void) read_statistics_for_tables_if_needed(thd, table_list);
+ thd->force_read_stats= false;
+
DEBUG_SYNC(thd, "after_open_table_ignore_flush");
/*
@@ -8101,8 +8101,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_statistics.cc b/sql/sql_statistics.cc
index 3c26f58073d..a3e446f5f20 100644
--- a/sql/sql_statistics.cc
+++ b/sql/sql_statistics.cc
@@ -3299,12 +3299,13 @@ int read_statistics_for_tables_if_needed(THD *thd, TABLE_LIST *tables)
if (table_share->stats_cb.stats_is_read)
tl->table->stats_is_read= TRUE;
if (thd->variables.optimizer_use_condition_selectivity > 3 &&
- table_share && !table_share->stats_cb.histograms_are_read)
+ table_share && table_share->stats_cb.stats_can_be_read &&
+ !table_share->stats_cb.histograms_are_read)
{
(void) read_histograms_for_table(thd, tl->table, stat_tables);
table_share->stats_cb.histograms_are_read= TRUE;
}
- if (table_share->stats_cb.stats_is_read)
+ if (table_share->stats_cb.histograms_are_read)
tl->table->histograms_are_read= TRUE;
}
}
@@ -4084,6 +4085,14 @@ bool is_stat_table(const char *db, const char *table)
bool is_eits_usable(Field *field)
{
+ Column_statistics* col_stats= field->read_stats;
+
+ // check if column_statistics was allocated for this field
+ if (!col_stats)
+ return false;
+
+ DBUG_ASSERT(field->table->stats_is_read);
+
/*
(1): checks if we have EITS statistics for a particular column
(2): Don't use EITS for GEOMETRY columns
@@ -4091,10 +4100,9 @@ bool is_eits_usable(Field *field)
partition list of a table. We assume the selecticivity for
such columns would be handled during partition pruning.
*/
- DBUG_ASSERT(field->table->stats_is_read);
- Column_statistics* col_stats= field->read_stats;
- return col_stats && !col_stats->no_stat_values_provided() && //(1)
- field->type() != MYSQL_TYPE_GEOMETRY && //(2)
+
+ return !col_stats->no_stat_values_provided() && //(1)
+ field->type() != MYSQL_TYPE_GEOMETRY && //(2)
#ifdef WITH_PARTITION_STORAGE_ENGINE
(!field->table->part_info ||
!field->table->part_info->field_in_partition_expr(field)) && //(3)
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 615de8b545a..6c84b9b21fb 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -942,6 +942,27 @@ String *copy_if_not_alloced(String *to,String *from,uint32 from_length)
(void) from->realloc(from_length);
return from;
}
+ if (from->uses_buffer_owned_by(to))
+ {
+ DBUG_ASSERT(!from->alloced);
+ DBUG_ASSERT(to->alloced);
+ /*
+ "from" is a constant string pointing to a fragment of alloced string "to":
+ to= xxxFFFyyy
+ - FFF is the part of "to" pointed by "from"
+ - xxx is the part of "to" before "from"
+ - yyy is the part of "to" after "from"
+ */
+ uint32 xxx_length= (uint32) (from->ptr() - to->ptr());
+ uint32 yyy_length= (uint32) (to->end() - from->end());
+ DBUG_ASSERT(to->length() >= yyy_length);
+ to->length(to->length() - yyy_length); // Remove the "yyy" part
+ DBUG_ASSERT(to->length() >= xxx_length);
+ to->replace(0, xxx_length, "", 0); // Remove the "xxx" part
+ to->realloc(from_length);
+ to->str_charset= from->str_charset;
+ return to;
+ }
if (to->realloc(from_length))
return from; // Actually an error
if ((to->str_length=MY_MIN(from->str_length,from_length)))
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 1da265d7c16..5ce9eb3c379 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -1366,6 +1366,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
@@ -1386,10 +1389,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);
/*
@@ -1437,6 +1440,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
*/
@@ -1464,6 +1470,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
{
@@ -1486,7 +1497,6 @@ int mysql_multi_update_prepare(THD *thd)
tl->lock_type= lock_type;
else
tl->set_lock_type(thd, lock_type);
- tl->updating= 0;
}
}
@@ -1495,6 +1505,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;
@@ -1523,7 +1547,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 0cff47437c8..0684e6ebcc5 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -443,7 +443,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);
}
@@ -1540,6 +1540,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 5b8c3c6c7ec..f45456e88d4 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -8703,7 +8703,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
@@ -8711,7 +8711,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;
}
;
@@ -12347,7 +12347,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
@@ -12364,7 +12364,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
@@ -12542,14 +12542,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;
}
/*
@@ -12557,7 +12557,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 {}
;
@@ -15565,13 +15565,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 5337a506215..e1c28212121 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -5989,7 +5989,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 c3ce5b8af51..e72e2bb2902 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -1779,6 +1779,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);
}
diff --git a/sql/win_tzname_data.h b/sql/win_tzname_data.h
new file mode 100644
index 00000000000..28a14ab7c11
--- /dev/null
+++ b/sql/win_tzname_data.h
@@ -0,0 +1,136 @@
+/* This file was generated using gen_win_tzname_data.ps1 */
+{L"Dateline Standard Time","Etc/GMT+12"},
+{L"UTC-11","Etc/GMT+11"},
+{L"Aleutian Standard Time","America/Adak"},
+{L"Hawaiian Standard Time","Pacific/Honolulu"},
+{L"Marquesas Standard Time","Pacific/Marquesas"},
+{L"Alaskan Standard Time","America/Anchorage"},
+{L"UTC-09","Etc/GMT+9"},
+{L"Pacific Standard Time (Mexico)","America/Tijuana"},
+{L"UTC-08","Etc/GMT+8"},
+{L"Pacific Standard Time","America/Los_Angeles"},
+{L"US Mountain Standard Time","America/Phoenix"},
+{L"Mountain Standard Time (Mexico)","America/Chihuahua"},
+{L"Mountain Standard Time","America/Denver"},
+{L"Central America Standard Time","America/Guatemala"},
+{L"Central Standard Time","America/Chicago"},
+{L"Easter Island Standard Time","Pacific/Easter"},
+{L"Central Standard Time (Mexico)","America/Mexico_City"},
+{L"Canada Central Standard Time","America/Regina"},
+{L"SA Pacific Standard Time","America/Bogota"},
+{L"Eastern Standard Time (Mexico)","America/Cancun"},
+{L"Eastern Standard Time","America/New_York"},
+{L"Haiti Standard Time","America/Port-au-Prince"},
+{L"Cuba Standard Time","America/Havana"},
+{L"US Eastern Standard Time","America/Indianapolis"},
+{L"Paraguay Standard Time","America/Asuncion"},
+{L"Atlantic Standard Time","America/Halifax"},
+{L"Venezuela Standard Time","America/Caracas"},
+{L"Central Brazilian Standard Time","America/Cuiaba"},
+{L"SA Western Standard Time","America/La_Paz"},
+{L"Pacific SA Standard Time","America/Santiago"},
+{L"Turks And Caicos Standard Time","America/Grand_Turk"},
+{L"Newfoundland Standard Time","America/St_Johns"},
+{L"Tocantins Standard Time","America/Araguaina"},
+{L"E. South America Standard Time","America/Sao_Paulo"},
+{L"SA Eastern Standard Time","America/Cayenne"},
+{L"Argentina Standard Time","America/Buenos_Aires"},
+{L"Greenland Standard Time","America/Godthab"},
+{L"Montevideo Standard Time","America/Montevideo"},
+{L"Magallanes Standard Time","America/Punta_Arenas"},
+{L"Saint Pierre Standard Time","America/Miquelon"},
+{L"Bahia Standard Time","America/Bahia"},
+{L"UTC-02","Etc/GMT+2"},
+{L"Azores Standard Time","Atlantic/Azores"},
+{L"Cape Verde Standard Time","Atlantic/Cape_Verde"},
+{L"UTC","Etc/GMT"},
+{L"GMT Standard Time","Europe/London"},
+{L"Greenwich Standard Time","Atlantic/Reykjavik"},
+{L"W. Europe Standard Time","Europe/Berlin"},
+{L"Central Europe Standard Time","Europe/Budapest"},
+{L"Romance Standard Time","Europe/Paris"},
+{L"Morocco Standard Time","Africa/Casablanca"},
+{L"Sao Tome Standard Time","Africa/Sao_Tome"},
+{L"Central European Standard Time","Europe/Warsaw"},
+{L"W. Central Africa Standard Time","Africa/Lagos"},
+{L"Jordan Standard Time","Asia/Amman"},
+{L"GTB Standard Time","Europe/Bucharest"},
+{L"Middle East Standard Time","Asia/Beirut"},
+{L"Egypt Standard Time","Africa/Cairo"},
+{L"E. Europe Standard Time","Europe/Chisinau"},
+{L"Syria Standard Time","Asia/Damascus"},
+{L"West Bank Standard Time","Asia/Hebron"},
+{L"South Africa Standard Time","Africa/Johannesburg"},
+{L"FLE Standard Time","Europe/Kiev"},
+{L"Israel Standard Time","Asia/Jerusalem"},
+{L"Kaliningrad Standard Time","Europe/Kaliningrad"},
+{L"Sudan Standard Time","Africa/Khartoum"},
+{L"Libya Standard Time","Africa/Tripoli"},
+{L"Namibia Standard Time","Africa/Windhoek"},
+{L"Arabic Standard Time","Asia/Baghdad"},
+{L"Turkey Standard Time","Europe/Istanbul"},
+{L"Arab Standard Time","Asia/Riyadh"},
+{L"Belarus Standard Time","Europe/Minsk"},
+{L"Russian Standard Time","Europe/Moscow"},
+{L"E. Africa Standard Time","Africa/Nairobi"},
+{L"Iran Standard Time","Asia/Tehran"},
+{L"Arabian Standard Time","Asia/Dubai"},
+{L"Astrakhan Standard Time","Europe/Astrakhan"},
+{L"Azerbaijan Standard Time","Asia/Baku"},
+{L"Russia Time Zone 3","Europe/Samara"},
+{L"Mauritius Standard Time","Indian/Mauritius"},
+{L"Saratov Standard Time","Europe/Saratov"},
+{L"Georgian Standard Time","Asia/Tbilisi"},
+{L"Caucasus Standard Time","Asia/Yerevan"},
+{L"Afghanistan Standard Time","Asia/Kabul"},
+{L"West Asia Standard Time","Asia/Tashkent"},
+{L"Ekaterinburg Standard Time","Asia/Yekaterinburg"},
+{L"Pakistan Standard Time","Asia/Karachi"},
+{L"India Standard Time","Asia/Calcutta"},
+{L"Sri Lanka Standard Time","Asia/Colombo"},
+{L"Nepal Standard Time","Asia/Katmandu"},
+{L"Central Asia Standard Time","Asia/Almaty"},
+{L"Bangladesh Standard Time","Asia/Dhaka"},
+{L"Omsk Standard Time","Asia/Omsk"},
+{L"Myanmar Standard Time","Asia/Rangoon"},
+{L"SE Asia Standard Time","Asia/Bangkok"},
+{L"Altai Standard Time","Asia/Barnaul"},
+{L"W. Mongolia Standard Time","Asia/Hovd"},
+{L"North Asia Standard Time","Asia/Krasnoyarsk"},
+{L"N. Central Asia Standard Time","Asia/Novosibirsk"},
+{L"Tomsk Standard Time","Asia/Tomsk"},
+{L"China Standard Time","Asia/Shanghai"},
+{L"North Asia East Standard Time","Asia/Irkutsk"},
+{L"Singapore Standard Time","Asia/Singapore"},
+{L"W. Australia Standard Time","Australia/Perth"},
+{L"Taipei Standard Time","Asia/Taipei"},
+{L"Ulaanbaatar Standard Time","Asia/Ulaanbaatar"},
+{L"Aus Central W. Standard Time","Australia/Eucla"},
+{L"Transbaikal Standard Time","Asia/Chita"},
+{L"Tokyo Standard Time","Asia/Tokyo"},
+{L"North Korea Standard Time","Asia/Pyongyang"},
+{L"Korea Standard Time","Asia/Seoul"},
+{L"Yakutsk Standard Time","Asia/Yakutsk"},
+{L"Cen. Australia Standard Time","Australia/Adelaide"},
+{L"AUS Central Standard Time","Australia/Darwin"},
+{L"E. Australia Standard Time","Australia/Brisbane"},
+{L"AUS Eastern Standard Time","Australia/Sydney"},
+{L"West Pacific Standard Time","Pacific/Port_Moresby"},
+{L"Tasmania Standard Time","Australia/Hobart"},
+{L"Vladivostok Standard Time","Asia/Vladivostok"},
+{L"Lord Howe Standard Time","Australia/Lord_Howe"},
+{L"Bougainville Standard Time","Pacific/Bougainville"},
+{L"Russia Time Zone 10","Asia/Srednekolymsk"},
+{L"Magadan Standard Time","Asia/Magadan"},
+{L"Norfolk Standard Time","Pacific/Norfolk"},
+{L"Sakhalin Standard Time","Asia/Sakhalin"},
+{L"Central Pacific Standard Time","Pacific/Guadalcanal"},
+{L"Russia Time Zone 11","Asia/Kamchatka"},
+{L"New Zealand Standard Time","Pacific/Auckland"},
+{L"UTC+12","Etc/GMT-12"},
+{L"Fiji Standard Time","Pacific/Fiji"},
+{L"Chatham Islands Standard Time","Pacific/Chatham"},
+{L"UTC+13","Etc/GMT-13"},
+{L"Tonga Standard Time","Pacific/Tongatapu"},
+{L"Samoa Standard Time","Pacific/Apia"},
+{L"Line Islands Standard Time","Pacific/Kiritimati"},