summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorOleksandr Byelkin <sanja@mariadb.com>2019-05-12 17:20:23 +0200
committerOleksandr Byelkin <sanja@mariadb.com>2019-05-12 17:20:23 +0200
commitc51f85f8823a845cd4a6aa1b2aa5af18484b2ab0 (patch)
tree65c45f6100c13dad90c33b86dc68be268139b0b8 /sql
parenta89f199c64a1d2339de7c167ce64ec148061a4d3 (diff)
parent8ce702aa90c174566f4ac950e85cc7570bf9b647 (diff)
downloadmariadb-git-c51f85f8823a845cd4a6aa1b2aa5af18484b2ab0.tar.gz
Merge branch '10.2' into 10.3
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.h1
-rw-r--r--sql/item_sum.cc93
-rw-r--r--sql/item_sum.h8
-rw-r--r--sql/log_event.cc23
-rw-r--r--sql/log_event_old.cc19
-rw-r--r--sql/mysql_upgrade_service.cc3
-rw-r--r--sql/mysqld.cc48
-rw-r--r--sql/mysqld.h2
-rw-r--r--sql/share/errmsg-utf8.txt4
-rw-r--r--sql/sp_head.cc2
-rw-r--r--sql/sql_acl.cc33
-rw-r--r--sql/sql_base.cc102
-rw-r--r--sql/sql_base.h17
-rw-r--r--sql/sql_class.h1
-rw-r--r--sql/sql_db.cc22
-rw-r--r--sql/sql_db.h2
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_parse.cc16
-rw-r--r--sql/sql_select.cc54
-rw-r--r--sql/sql_show.cc1
-rw-r--r--sql/sql_statistics.cc20
-rw-r--r--sql/sql_string.cc21
-rw-r--r--sql/sql_table.cc95
-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_window.cc27
-rw-r--r--sql/sql_yacc.yy35
-rw-r--r--sql/sql_yacc_ora.yy35
-rw-r--r--sql/table.cc3
-rw-r--r--sql/table.h1
-rw-r--r--sql/win_tzname_data.h136
37 files changed, 659 insertions, 255 deletions
diff --git a/sql/events.cc b/sql/events.cc
index c3a578f1097..ce5f2b1bc10 100644
--- a/sql/events.cc
+++ b/sql/events.cc
@@ -418,6 +418,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 0f75772e485..d97c267009f 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -2397,7 +2397,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 6371c330170..2646a2a1225 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
@@ -10079,7 +10079,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 83e8bc2a60a..28faf9fc9ad 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
@@ -2219,6 +2219,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.h b/sql/item_func.h
index 80d90ae21c5..61491b34cf8 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -2466,6 +2466,7 @@ public:
void cleanup();
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_set_user_var>(thd, this); }
+ bool excl_dep_on_table(table_map tab_map) { return false; }
};
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index ce0c9d3e944..e27b61e9d22 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -3736,6 +3736,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),
@@ -3848,7 +3849,10 @@ void Item_func_group_concat::clear()
if (row_limit)
copy_row_limit= row_limit->val_int();
if (tree)
+ {
reset_tree(tree);
+ tree_len= 0;
+ }
if (unique_filter)
unique_filter->reset();
if (table && table->blob_storage)
@@ -3856,6 +3860,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, 0);
+ return 1;
+ }
+ delete_tree(tree, 0);
+ *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()
{
@@ -3865,6 +3925,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];
@@ -3872,8 +3935,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;
@@ -3891,11 +3959,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)
@@ -4026,10 +4101,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)
{
@@ -4089,10 +4173,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 b400ebd5f80..7152916498c 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -1750,6 +1750,7 @@ class Item_func_group_concat : public Item_sum
String *separator;
TREE tree_base;
TREE *tree;
+ size_t tree_len;
Item **ref_pointer_array;
/**
@@ -1796,6 +1797,9 @@ class Item_func_group_concat : public Item_sum
friend int dump_leaf_key(void* key_arg,
element_count count __attribute__((unused)),
void* item_arg);
+
+ bool repack_tree(THD *thd);
+
public:
Item_func_group_concat(THD *thd, Name_resolution_context *context_arg,
bool is_distinct, List<Item> *is_select,
@@ -1852,8 +1856,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)
{ return get_item_copy<Item_func_group_concat>(thd, this); }
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 52556cddd12..fa42e7b0a07 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"
@@ -11279,6 +11280,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;
@@ -11303,7 +11310,6 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
}
if (unlikely(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))
{
@@ -11316,23 +11322,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 b5381ec6d74..f56bc86127d 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 (unlikely(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/mysql_upgrade_service.cc b/sql/mysql_upgrade_service.cc
index 9ea78accf44..94ca10766d8 100644
--- a/sql/mysql_upgrade_service.cc
+++ b/sql/mysql_upgrade_service.cc
@@ -159,8 +159,9 @@ static void die(const char *fmt, ...)
#define WRITE_LOG(fmt,...) {\
char log_buf[1024]; \
+ DWORD nbytes; \
snprintf(log_buf,sizeof(log_buf), fmt, __VA_ARGS__);\
- WriteFile(logfile_handle,log_buf, (DWORD)strlen(log_buf), 0 , 0);\
+ WriteFile(logfile_handle,log_buf, (DWORD)strlen(log_buf), &nbytes , 0);\
}
/*
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index a824d0898d6..1f155b32903 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -4173,6 +4173,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()
{
@@ -4228,22 +4261,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/mysqld.h b/sql/mysqld.h
index dccf7436f80..cb57682bcfc 100644
--- a/sql/mysqld.h
+++ b/sql/mysqld.h
@@ -65,7 +65,7 @@ typedef Bitmap<((MAX_INDEXES+7)/8*8)> key_map; /* Used for finding keys */
#define OPT_SESSION SHOW_OPT_SESSION
#define OPT_GLOBAL SHOW_OPT_GLOBAL
-extern MY_TIMER_INFO sys_timer_info;
+extern MYSQL_PLUGIN_IMPORT MY_TIMER_INFO sys_timer_info;
/*
Values for --slave-parallel-mode
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index 74aed792f1d..99af1c60287 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/sp_head.cc b/sql/sp_head.cc
index 924fd04007e..747bf92dbf9 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -1496,7 +1496,7 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
NULL. In this case, mysql_change_db() would generate an error.
*/
- err_status|= mysql_change_db(thd, (LEX_CSTRING*) &saved_cur_db_name, TRUE);
+ err_status|= mysql_change_db(thd, (LEX_CSTRING*)&saved_cur_db_name, TRUE) != 0;
}
m_flags&= ~IS_INVOKED;
if (m_parent)
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index ed200bba763..60697ab3449 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -770,8 +770,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;
}
@@ -1772,6 +1771,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+)
@@ -12092,7 +12097,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)
{
@@ -13526,10 +13531,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 ddb8fee6f70..73817ddb722 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -3362,6 +3362,47 @@ 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;
+ bool maybe_need_prelocking=
+ (tables->updating && tables->lock_type >= TL_WRITE_ALLOW_WRITE)
+ || thd->lex->default_used;
+
+ if (thd->locked_tables_mode <= LTM_LOCK_TABLES &&
+ ! has_prelocking_list && maybe_need_prelocking)
+ {
+ 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
@@ -3388,14 +3429,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");
@@ -3670,38 +3710,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 || thd->lex->default_used))
- {
- 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 (unlikely(error))
- goto end;
- }
+ error= extend_table_list(thd, tables, prelocking_strategy, has_prelocking_list);
+ if (unlikely(error))
+ goto end;
/* Copy grant information from TABLE_LIST instance to TABLE one. */
tables->table->grant= tables->grant;
@@ -3879,8 +3890,8 @@ lock_table_names(THD *thd, const DDL_options_st &options,
if (create_table)
#ifdef WITH_WSREP
- if (thd->lex->sql_command != SQLCOM_CREATE_TABLE &&
- thd->wsrep_exec_mode != REPL_RECV)
+ if (!(thd->lex->sql_command == SQLCOM_CREATE_TABLE &&
+ thd->wsrep_exec_mode == REPL_RECV))
#endif
lock_wait_timeout= 0; // Don't wait for timeout
}
@@ -3892,6 +3903,7 @@ lock_table_names(THD *thd, const DDL_options_st &options,
bool res= thd->mdl_context.acquire_locks(&mdl_requests, lock_wait_timeout);
if (create_table)
thd->pop_internal_handler();
+
if (!res)
DBUG_RETURN(FALSE); // Got locks
@@ -4026,7 +4038,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)
{
/*
@@ -4069,7 +4082,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);
@@ -4139,9 +4152,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 (unlikely(error))
{
@@ -8688,8 +8701,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);
size_t ext_len= strlen(ext);
diff --git a/sql/sql_base.h b/sql/sql_base.h
index 22247af07a8..5c2ff18b170 100644
--- a/sql/sql_base.h
+++ b/sql/sql_base.h
@@ -240,8 +240,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)
@@ -505,6 +516,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.h b/sql/sql_class.h
index 221e453eab5..2a949856879 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -38,6 +38,7 @@
#include "thr_timer.h"
#include "thr_malloc.h"
#include "log_slow.h" /* LOG_SLOW_DISABLE_... */
+#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 cce0bdadedb..957b676f81f 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -1441,12 +1441,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_CSTRING *new_db_name,
+uint mysql_change_db(THD *thd, const LEX_CSTRING *new_db_name,
bool force_switch)
{
LEX_CSTRING new_db_file_name;
@@ -1477,7 +1477,7 @@ bool mysql_change_db(THD *thd, const LEX_CSTRING *new_db_name,
{
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));
@@ -1503,7 +1503,7 @@ bool mysql_change_db(THD *thd, const LEX_CSTRING *new_db_name,
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,
@@ -1523,7 +1523,7 @@ bool mysql_change_db(THD *thd, const LEX_CSTRING *new_db_name,
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));
@@ -1553,7 +1553,7 @@ bool mysql_change_db(THD *thd, const LEX_CSTRING *new_db_name,
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(const_cast<char*>(new_db_file_name.str));
- DBUG_RETURN(TRUE);
+ DBUG_RETURN(ER_DBACCESS_DENIED_ERROR);
}
#endif
@@ -1587,7 +1587,7 @@ bool mysql_change_db(THD *thd, const LEX_CSTRING *new_db_name,
/* The operation failed. */
- DBUG_RETURN(TRUE);
+ DBUG_RETURN(ER_BAD_DB_ERROR);
}
}
@@ -1603,7 +1603,7 @@ bool mysql_change_db(THD *thd, const LEX_CSTRING *new_db_name,
done:
SESSION_TRACKER_CHANGED(thd, CURRENT_SCHEMA_TRACKER, NULL);
SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
- DBUG_RETURN(FALSE);
+ DBUG_RETURN(0);
}
@@ -1851,7 +1851,7 @@ bool mysql_upgrade_db(THD *thd, const LEX_CSTRING *old_db)
/* Step9: Let's do "use newdb" if we renamed the current database */
if (change_to_newdb)
- error|= mysql_change_db(thd, & new_db, FALSE);
+ error|= mysql_change_db(thd, & new_db, FALSE) != 0;
exit:
DBUG_RETURN(error);
diff --git a/sql/sql_db.h b/sql/sql_db.h
index c0646bd65f0..7eee86fa7c8 100644
--- a/sql/sql_db.h
+++ b/sql/sql_db.h
@@ -26,7 +26,7 @@ bool mysql_alter_db(THD *thd, const LEX_CSTRING *db,
const Schema_specification_st *create);
bool mysql_rm_db(THD *thd, const LEX_CSTRING *db, bool if_exists);
bool mysql_upgrade_db(THD *thd, const LEX_CSTRING *old_db);
-bool mysql_change_db(THD *thd, const LEX_CSTRING *new_db_name,
+uint mysql_change_db(THD *thd, const LEX_CSTRING *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 24383b1949c..40d6799ece7 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -1229,7 +1229,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 ab649f23160..7a74f322dc1 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -3406,9 +3406,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;
}
/*
@@ -4602,6 +4599,16 @@ end_with_restore_list:
res= 0;
unit->set_limit(select_lex);
+ /*
+ 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
@@ -8680,9 +8687,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 7b98a235ab0..20551285d70 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1219,8 +1219,9 @@ JOIN::prepare(TABLE_LIST *tables_init,
item->max_length)))
real_order= TRUE;
- if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM)
- item->split_sum_func(thd, ref_ptrs, all_fields, 0);
+ if ((item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM) ||
+ item->with_window_func)
+ item->split_sum_func(thd, ref_ptrs, all_fields, SPLIT_SUM_SELECT);
}
if (!real_order)
order= NULL;
@@ -9381,7 +9382,7 @@ JOIN_TAB *next_linear_tab(JOIN* join, JOIN_TAB* tab,
}
/* If no more JOIN_TAB's on the top level */
- if (++tab == join->join_tab + join->top_join_tab_count + join->aggr_tables)
+ if (++tab >= join->join_tab + join->exec_join_tab_cnt() + join->aggr_tables)
return NULL;
if (include_bush_roots == WITHOUT_BUSH_ROOTS && tab->bush_children)
@@ -17023,28 +17024,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);
@@ -23215,6 +23216,10 @@ int setup_order(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
my_error(ER_WINDOW_FUNCTION_IN_WINDOW_SPEC, MYF(0));
return 1;
}
+ if (from_window_spec && (*order->item)->with_sum_func &&
+ (*order->item)->type() != Item::SUM_FUNC_ITEM)
+ (*order->item)->split_sum_func(thd, ref_pointer_array,
+ all_fields, SPLIT_SUM_SELECT);
}
return 0;
}
@@ -23282,6 +23287,10 @@ setup_group(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
my_error(ER_WINDOW_FUNCTION_IN_WINDOW_SPEC, MYF(0));
return 1;
}
+ if (from_window_spec && (*ord->item)->with_sum_func &&
+ (*ord->item)->type() != Item::SUM_FUNC_ITEM)
+ (*ord->item)->split_sum_func(thd, ref_pointer_array,
+ all_fields, SPLIT_SUM_SELECT);
}
if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY &&
context_analysis_place == IN_GROUP_BY)
@@ -27441,27 +27450,6 @@ AGGR_OP::end_send()
}
else
{
- /*
- In case we have window functions present, an extra step is required
- to compute all the fields from the temporary table.
- In case we have a compound expression such as: expr + expr,
- where one of the terms has a window function inside it, only
- after computing window function values we actually know the true
- final result of the compounded expression.
-
- Go through all the func items and save their values once again in the
- corresponding temp table fields. Do this for each row in the table.
- */
- if (join_tab->window_funcs_step)
- {
- Item **func_ptr= join_tab->tmp_table_param->items_to_copy;
- Item *func;
- for (; (func = *func_ptr) ; func_ptr++)
- {
- if (func->with_window_func)
- func->save_in_result_field(true);
- }
- }
rc= evaluate_join_record(join, join_tab, 0);
}
}
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index fe8ed5076a8..8ec5435fd45 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -8520,7 +8520,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.str,
table_list->alias.str);
- table_list->table_name= table->s->table_name;
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 c751b079147..02598897028 100644
--- a/sql/sql_statistics.cc
+++ b/sql/sql_statistics.cc
@@ -3293,12 +3293,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;
}
}
@@ -4077,6 +4078,14 @@ bool is_stat_table(const LEX_CSTRING *db, LEX_CSTRING *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
@@ -4084,10 +4093,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 cc77452ecd1..fa27bc968da 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -996,6 +996,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_table.cc b/sql/sql_table.cc
index cbea0c6cbfd..513b6a2e2f3 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -8811,6 +8811,52 @@ static bool fk_prepare_copy_alter_table(THD *thd, TABLE *table,
}
}
+ /*
+ Normally, an attempt to modify an FK parent table will cause
+ FK children to be prelocked, so the table-being-altered cannot
+ be modified by a cascade FK action, because ALTER holds a lock
+ and prelocking will wait.
+
+ But if a new FK is being added by this very ALTER, then the target
+ table is not locked yet (it's a temporary table). So, we have to
+ lock FK parents explicitly.
+ */
+ if (alter_info->flags & ALTER_ADD_FOREIGN_KEY)
+ {
+ List_iterator<Key> fk_list_it(alter_info->key_list);
+
+ while (Key *key= fk_list_it++)
+ {
+ if (key->type != Key::FOREIGN_KEY)
+ continue;
+
+ Foreign_key *fk= static_cast<Foreign_key*>(key);
+ char dbuf[NAME_LEN];
+ char tbuf[NAME_LEN];
+ const char *ref_db= (fk->ref_db.str ?
+ fk->ref_db.str :
+ alter_ctx->new_db.str);
+ const char *ref_table= fk->ref_table.str;
+ MDL_request mdl_request;
+
+ if (lower_case_table_names)
+ {
+ strmake_buf(dbuf, ref_db);
+ my_casedn_str(system_charset_info, dbuf);
+ strmake_buf(tbuf, ref_table);
+ my_casedn_str(system_charset_info, tbuf);
+ ref_db= dbuf;
+ ref_table= tbuf;
+ }
+
+ mdl_request.init(MDL_key::TABLE, ref_db, ref_table, MDL_SHARED_NO_WRITE,
+ MDL_TRANSACTION);
+ if (thd->mdl_context.acquire_lock(&mdl_request,
+ thd->variables.lock_wait_timeout))
+ DBUG_RETURN(true);
+ }
+ }
+
DBUG_RETURN(false);
}
@@ -9812,6 +9858,7 @@ do_continue:;
/* Mark that we have created table in storage engine. */
no_ha_table= false;
+ DEBUG_SYNC(thd, "alter_table_intermediate_table_created");
new_table=
thd->create_and_open_tmp_table(new_db_type, &frm, alter_ctx.get_tmp_path(),
@@ -9827,54 +9874,6 @@ do_continue:;
/* in case of alter temp table send the tracker in OK packet */
SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
}
- else
- {
- /*
- Normally, an attempt to modify an FK parent table will cause
- FK children to be prelocked, so the table-being-altered cannot
- be modified by a cascade FK action, because ALTER holds a lock
- and prelocking will wait.
-
- But if a new FK is being added by this very ALTER, then the target
- table is not locked yet (it's a temporary table). So, we have to
- lock FK parents explicitly.
- */
- if (alter_info->flags & ALTER_ADD_FOREIGN_KEY)
- {
- List <FOREIGN_KEY_INFO> fk_list;
- List_iterator<FOREIGN_KEY_INFO> fk_list_it(fk_list);
- FOREIGN_KEY_INFO *fk;
-
- /* tables_opened can be > 1 only for MERGE tables */
- DBUG_ASSERT(tables_opened == 1);
- DBUG_ASSERT(&table_list->next_global == thd->lex->query_tables_last);
-
- new_table->file->get_foreign_key_list(thd, &fk_list);
- while ((fk= fk_list_it++))
- {
- MDL_request mdl_request;
-
- if (lower_case_table_names)
- {
- char buf[NAME_LEN];
- size_t len;
- strmake_buf(buf, fk->referenced_db->str);
- len = my_casedn_str(files_charset_info, buf);
- thd->make_lex_string(fk->referenced_db, buf, len);
- strmake_buf(buf, fk->referenced_table->str);
- len = my_casedn_str(files_charset_info, buf);
- thd->make_lex_string(fk->referenced_table, buf, len);
- }
-
- mdl_request.init(MDL_key::TABLE,
- fk->referenced_db->str, fk->referenced_table->str,
- MDL_SHARED_NO_WRITE, MDL_TRANSACTION);
- if (thd->mdl_context.acquire_lock(&mdl_request,
- thd->variables.lock_wait_timeout))
- goto err_new_table_cleanup;
- }
- }
- }
/*
Note: In case of MERGE table, we do not attach children. We do not
diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc
index bab9bb5e9ac..d87fe13b10e 100644
--- a/sql/sql_truncate.cc
+++ b/sql/sql_truncate.cc
@@ -147,15 +147,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(!lex_string_cmp(system_charset_info,
- fk_info->referenced_db,
- &table->s->db));
-
- DBUG_ASSERT(!lex_string_cmp(system_charset_info,
- fk_info->referenced_table,
- &table->s->table_name));
-
- if (lex_string_cmp(system_charset_info, fk_info->foreign_db,
+ if (lex_string_cmp(system_charset_info, fk_info->referenced_db,
+ &table->s->db) ||
+ lex_string_cmp(system_charset_info, fk_info->referenced_table,
+ &table->s->table_name) ||
+ lex_string_cmp(system_charset_info, fk_info->foreign_db,
&table->s->db) ||
lex_string_cmp(system_charset_info, fk_info->foreign_table,
&table->s->table_name))
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 497f419c1db..32ac28f6e46 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -1536,6 +1536,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
@@ -1556,10 +1559,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);
/*
@@ -1608,6 +1611,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
*/
@@ -1635,6 +1641,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
{
@@ -1657,7 +1668,6 @@ int mysql_multi_update_prepare(THD *thd)
tl->lock_type= lock_type;
else
tl->set_lock_type(thd, lock_type);
- tl->updating= 0;
}
}
@@ -1666,6 +1676,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;
@@ -1694,7 +1718,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 50416940960..b85243dc134 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -442,7 +442,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);
}
@@ -1554,6 +1554,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
if (!tbl->sequence)
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_window.cc b/sql/sql_window.cc
index 86c40b5f58f..487242933d4 100644
--- a/sql/sql_window.cc
+++ b/sql/sql_window.cc
@@ -2710,11 +2710,38 @@ bool save_window_function_values(List<Item_window_func>& window_functions,
TABLE *tbl, uchar *rowid_buf)
{
List_iterator_fast<Item_window_func> iter(window_functions);
+ JOIN_TAB *join_tab= tbl->reginfo.join_tab;
tbl->file->ha_rnd_pos(tbl->record[0], rowid_buf);
store_record(tbl, record[1]);
while (Item_window_func *item_win= iter++)
item_win->save_in_field(item_win->result_field, true);
+ /*
+ In case we have window functions present, an extra step is required
+ to compute all the fields from the temporary table.
+ In case we have a compound expression such as: expr + expr,
+ where one of the terms has a window function inside it, only
+ after computing window function values we actually know the true
+ final result of the compounded expression.
+
+ Go through all the func items and save their values once again in the
+ corresponding temp table fields. Do this for each row in the table.
+
+ This needs to be done earlier because ORDER BY clause can also have
+ a window function, so we need to make sure all the fields of the temp.table
+ are updated before we do the filesort. So is best to update the other fields
+ that contain the window functions along with the computation of window
+ functions.
+ */
+
+ Item **func_ptr= join_tab->tmp_table_param->items_to_copy;
+ Item *func;
+ for (; (func = *func_ptr) ; func_ptr++)
+ {
+ if (func->with_window_func && func->type() != Item::WINDOW_FUNC_ITEM)
+ func->save_in_result_field(true);
+ }
+
int err= tbl->file->ha_update_row(tbl->record[1], tbl->record[0]);
if (err && err != HA_ERR_RECORD_IS_THE_SAME)
return true;
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 8910d7418fd..6414609f643 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -9540,7 +9540,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 opt_lock_wait_timeout
@@ -9548,7 +9548,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;
}
;
@@ -13416,7 +13416,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
@@ -13433,7 +13433,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
@@ -13666,14 +13666,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 (unlikely(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 (unlikely(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.str, "UPDATE");
+ slex->get_table_list()->alias.str, "UPDATE");
MYSQL_YYABORT;
}
/*
@@ -13681,7 +13681,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 {}
;
@@ -16692,13 +16692,16 @@ table_lock:
{
thr_lock_type lock_type= (thr_lock_type) $3;
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 (unlikely(!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))))
+ add_table_to_list(thd, $1, $2, table_options,
+ lock_type, mdl_type)))
MYSQL_YYABORT;
}
;
diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy
index 1c83462e6ac..40315c05056 100644
--- a/sql/sql_yacc_ora.yy
+++ b/sql/sql_yacc_ora.yy
@@ -9477,7 +9477,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 opt_lock_wait_timeout
@@ -9485,7 +9485,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;
}
;
@@ -13377,7 +13377,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
@@ -13394,7 +13394,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
@@ -13627,14 +13627,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 (unlikely(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 (unlikely(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.str, "UPDATE");
+ slex->get_table_list()->alias.str, "UPDATE");
MYSQL_YYABORT;
}
/*
@@ -13642,7 +13642,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 {}
;
@@ -16745,13 +16745,16 @@ table_lock:
{
thr_lock_type lock_type= (thr_lock_type) $3;
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 (unlikely(!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))))
+ 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 7042959215d..e46af771507 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -6099,7 +6099,8 @@ const char *Field_iterator_table_ref::get_table_name()
return natural_join_it.column_ref()->safe_table_name();
DBUG_ASSERT(!strcmp(table_ref->table_name.str,
- table_ref->table->s->table_name.str));
+ table_ref->table->s->table_name.str) ||
+ table_ref->schema_table);
return table_ref->table_name.str;
}
diff --git a/sql/table.h b/sql/table.h
index b7c14e0a606..abef6e44806 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -1949,6 +1949,7 @@ struct TABLE_LIST
table_name= *table_name_arg;
alias= (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.str, table_name.str, 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"},