diff options
author | Oleksandr Byelkin <sanja@mariadb.com> | 2019-05-04 17:04:55 +0200 |
---|---|---|
committer | Oleksandr Byelkin <sanja@mariadb.com> | 2019-05-04 17:04:55 +0200 |
commit | 8cbb14ef5d180687f131bc44a4e8fc84083d033c (patch) | |
tree | 091f11e2d20f95656a7b12294782eb0488fd4fcc /sql | |
parent | 4345868382ca3525de5eb432302b6b9b957b47c1 (diff) | |
parent | b85aa20065504bdda4bc03c2bd7eb7de38865c5d (diff) | |
download | mariadb-git-8cbb14ef5d180687f131bc44a4e8fc84083d033c.tar.gz |
Merge branch '10.1' into 10.2
Diffstat (limited to 'sql')
-rw-r--r-- | sql/events.cc | 6 | ||||
-rw-r--r-- | sql/field.cc | 2 | ||||
-rw-r--r-- | sql/gen_win_tzname_data.ps1 | 11 | ||||
-rw-r--r-- | sql/ha_partition.cc | 11 | ||||
-rw-r--r-- | sql/handler.h | 5 | ||||
-rw-r--r-- | sql/item_func.cc | 6 | ||||
-rw-r--r-- | sql/item_sum.cc | 93 | ||||
-rw-r--r-- | sql/item_sum.h | 9 | ||||
-rw-r--r-- | sql/log_event.cc | 23 | ||||
-rw-r--r-- | sql/log_event_old.cc | 19 | ||||
-rw-r--r-- | sql/mysqld.cc | 48 | ||||
-rw-r--r-- | sql/share/errmsg-utf8.txt | 4 | ||||
-rw-r--r-- | sql/sql_acl.cc | 33 | ||||
-rw-r--r-- | sql/sql_base.cc | 95 | ||||
-rw-r--r-- | sql/sql_base.h | 17 | ||||
-rw-r--r-- | sql/sql_class.cc | 1 | ||||
-rw-r--r-- | sql/sql_class.h | 1 | ||||
-rw-r--r-- | sql/sql_db.cc | 20 | ||||
-rw-r--r-- | sql/sql_db.h | 2 | ||||
-rw-r--r-- | sql/sql_lex.h | 4 | ||||
-rw-r--r-- | sql/sql_parse.cc | 16 | ||||
-rw-r--r-- | sql/sql_select.cc | 18 | ||||
-rw-r--r-- | sql/sql_show.cc | 10 | ||||
-rw-r--r-- | sql/sql_statistics.cc | 20 | ||||
-rw-r--r-- | sql/sql_string.cc | 21 | ||||
-rw-r--r-- | sql/sql_truncate.cc | 14 | ||||
-rw-r--r-- | sql/sql_update.cc | 36 | ||||
-rw-r--r-- | sql/sql_view.cc | 3 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 37 | ||||
-rw-r--r-- | sql/table.cc | 3 | ||||
-rw-r--r-- | sql/table.h | 1 | ||||
-rw-r--r-- | sql/win_tzname_data.h | 136 |
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, ©_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"}, |