summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2015-11-19 15:52:14 +0100
committerSergei Golubchik <serg@mariadb.org>2015-11-19 15:52:14 +0100
commitbeded7d9c9592ca8fdfc367f7c64f89c35995c44 (patch)
treea215a54ed5043bb17fe7d69a69439e05b21682d5 /sql
parentaf71da5d2f90c82b2357e808640003907c488bc2 (diff)
parent2553f143fdeb9068eb02a8fda58750c24071f5ef (diff)
downloadmariadb-git-beded7d9c9592ca8fdfc367f7c64f89c35995c44.tar.gz
Merge branch '10.0' into 10.1
Diffstat (limited to 'sql')
-rw-r--r--sql/events.cc177
-rw-r--r--sql/events.h16
-rw-r--r--sql/filesort.cc1
-rw-r--r--sql/ha_partition.cc1
-rw-r--r--sql/handler.cc2
-rw-r--r--sql/hostname.cc1
-rw-r--r--sql/item.cc22
-rw-r--r--sql/item.h3
-rw-r--r--sql/key.cc1
-rw-r--r--sql/lock.cc1
-rw-r--r--sql/log.cc2
-rw-r--r--sql/mysqld.cc10
-rw-r--r--sql/opt_sum.cc6
-rw-r--r--sql/protocol.cc1
-rw-r--r--sql/records.cc5
-rw-r--r--sql/records.h2
-rw-r--r--sql/rpl_injector.cc1
-rw-r--r--sql/rpl_mi.cc1
-rw-r--r--sql/rpl_record_old.cc1
-rw-r--r--sql/sql_acl.cc7
-rw-r--r--sql/sql_base.cc35
-rw-r--r--sql/sql_base.h1
-rw-r--r--sql/sql_class.cc1
-rw-r--r--sql/sql_class.h6
-rw-r--r--sql/sql_connect.cc1
-rw-r--r--sql/sql_const.h4
-rw-r--r--sql/sql_delete.cc17
-rw-r--r--sql/sql_digest.h7
-rw-r--r--sql/sql_error.cc2
-rw-r--r--sql/sql_handler.cc1
-rw-r--r--sql/sql_insert.cc1
-rw-r--r--sql/sql_lex.cc24
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_manager.cc1
-rw-r--r--sql/sql_parse.cc4
-rw-r--r--sql/sql_partition.cc1
-rw-r--r--sql/sql_prepare.cc10
-rw-r--r--sql/sql_profile.cc1
-rw-r--r--sql/sql_reload.cc1
-rw-r--r--sql/sql_rename.cc3
-rw-r--r--sql/sql_select.cc6
-rw-r--r--sql/sql_statistics.cc142
-rw-r--r--sql/sql_table.cc11
-rw-r--r--sql/sql_time.cc1
-rw-r--r--sql/sql_trigger.h2
-rw-r--r--sql/sql_update.cc65
-rw-r--r--sql/sql_update.h1
-rw-r--r--sql/sql_view.cc5
-rw-r--r--sql/sql_yacc.yy15
-rw-r--r--sql/sys_vars.cc42
-rw-r--r--sql/table.cc1
51 files changed, 455 insertions, 220 deletions
diff --git a/sql/events.cc b/sql/events.cc
index 2bb112867bf..abc798b659a 100644
--- a/sql/events.cc
+++ b/sql/events.cc
@@ -80,7 +80,8 @@ Event_queue *Events::event_queue;
Event_scheduler *Events::scheduler;
Event_db_repository *Events::db_repository;
ulong Events::opt_event_scheduler= Events::EVENTS_OFF;
-bool Events::check_system_tables_error= FALSE;
+ulong Events::startup_state= Events::EVENTS_OFF;
+ulong Events::inited;
/*
@@ -114,7 +115,7 @@ bool Events::check_if_system_tables_error()
{
DBUG_ENTER("Events::check_if_system_tables_error");
- if (check_system_tables_error)
+ if (!inited)
{
my_error(ER_EVENTS_DB_ERROR, MYF(0));
DBUG_RETURN(TRUE);
@@ -257,10 +258,10 @@ common_1_lev_code:
/**
- Create a new query string for removing executable comments
- for avoiding leak and keeping consistency of the execution
+ Create a new query string for removing executable comments
+ for avoiding leak and keeping consistency of the execution
on master and slave.
-
+
@param[in] thd Thread handler
@param[in] buf Query string
@@ -287,7 +288,7 @@ create_query_string(THD *thd, String *buf)
thd->lex->stmt_definition_end -
thd->lex->stmt_definition_begin))
return 1;
-
+
return 0;
}
@@ -340,8 +341,8 @@ Events::create_event(THD *thd, Event_parse_data *parse_data)
if (parse_data->do_not_create)
DBUG_RETURN(FALSE);
- /*
- Turn off row binlogging of this statement and use statement-based
+ /*
+ Turn off row binlogging of this statement and use statement-based
so that all supporting tables are updated for CREATE EVENT command.
*/
save_binlog_format= thd->set_current_stmt_binlog_format_stmt();
@@ -392,8 +393,10 @@ Events::create_event(THD *thd, Event_parse_data *parse_data)
String log_query(buffer, sizeof(buffer), &my_charset_bin);
if (create_query_string(thd, &log_query))
{
- sql_print_error("Event Error: An error occurred while creating query "
- "string, before writing it into binary log.");
+ my_message_sql(ER_STARTUP,
+ "Event Error: An error occurred while creating query "
+ "string, before writing it into binary log.",
+ MYF(ME_NOREFRESH));
ret= true;
}
else
@@ -481,8 +484,8 @@ Events::update_event(THD *thd, Event_parse_data *parse_data,
}
}
- /*
- Turn off row binlogging of this statement and use statement-based
+ /*
+ Turn off row binlogging of this statement and use statement-based
so that all supporting tables are updated for UPDATE EVENT command.
*/
save_binlog_format= thd->set_current_stmt_binlog_format_stmt();
@@ -769,6 +772,13 @@ Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */)
int ret;
DBUG_ENTER("Events::fill_schema_events");
+ /*
+ If we didn't start events because of --skip-grant-tables, return an
+ empty set
+ */
+ if (opt_noacl)
+ DBUG_RETURN(0);
+
if (check_if_system_tables_error())
DBUG_RETURN(1);
@@ -797,6 +807,7 @@ Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */)
/**
Initializes the scheduler's structures.
+ @param THD or null (if called by init)
@param opt_noacl_or_bootstrap
TRUE if there is --skip-grant-tables or --bootstrap
option. In that case we disable the event scheduler.
@@ -804,44 +815,56 @@ Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */)
@note This function is not synchronized.
@retval FALSE Perhaps there was an error, and the event scheduler
- is disabled. But the error is not fatal and the
+ is disabled. But the error is not fatal and the
server start up can continue.
@retval TRUE Fatal error. Startup must terminate (call unireg_abort()).
*/
bool
-Events::init(bool opt_noacl_or_bootstrap)
+Events::init(THD *thd, bool opt_noacl_or_bootstrap)
{
-
- THD *thd;
int err_no;
bool res= FALSE;
-
+ bool had_thd= thd != 0;
DBUG_ENTER("Events::init");
+ DBUG_ASSERT(inited == 0);
+
+ /*
+ Was disabled explicitly from the command line
+ */
+ if (opt_event_scheduler == Events::EVENTS_DISABLED ||
+ opt_noacl_or_bootstrap)
+ DBUG_RETURN(FALSE);
+
/* We need a temporary THD during boot */
- if (!(thd= new THD()))
+ if (!thd)
{
- res= TRUE;
- goto end;
+
+ if (!(thd= new THD()))
+ {
+ res= TRUE;
+ goto end;
+ }
+ /*
+ The thread stack does not start from this function but we cannot
+ guess the real value. So better some value that doesn't assert than
+ no value.
+ */
+ thd->thread_stack= (char*) &thd;
+ thd->store_globals();
+ /*
+ Set current time for the thread that handles events.
+ Current time is stored in data member start_time of THD class.
+ Subsequently, this value is used to check whether event was expired
+ when make loading events from storage. Check for event expiration time
+ is done at Event_queue_element::compute_next_execution_time() where
+ event's status set to Event_parse_data::DISABLED and dropped flag set
+ to true if event was expired.
+ */
+ thd->set_time();
}
- /*
- The thread stack does not start from this function but we cannot
- guess the real value. So better some value that doesn't assert than
- no value.
- */
- thd->thread_stack= (char*) &thd;
- thd->store_globals();
- /*
- Set current time for the thread that handles events.
- Current time is stored in data member start_time of THD class.
- Subsequently, this value is used to check whether event was expired
- when make loading events from storage. Check for event expiration time
- is done at Event_queue_element::compute_next_execution_time() where
- event's status set to Event_parse_data::DISABLED and dropped flag set
- to true if event was expired.
- */
- thd->set_time();
+
/*
We will need Event_db_repository anyway, even if the scheduler is
disabled - to perform events DDL.
@@ -861,28 +884,19 @@ Events::init(bool opt_noacl_or_bootstrap)
are most likely not there and we're going to disable the event
scheduler anyway.
*/
- if (opt_noacl_or_bootstrap || Event_db_repository::check_system_tables(thd))
+ if (Event_db_repository::check_system_tables(thd))
{
- if (! opt_noacl_or_bootstrap)
- {
- sql_print_error("Event Scheduler: An error occurred when initializing "
- "system tables. Disabling the Event Scheduler.");
- check_system_tables_error= TRUE;
- }
-
+ delete db_repository;
+ db_repository= 0;
+ my_message(ER_STARTUP,
+ "Event Scheduler: An error occurred when initializing "
+ "system tables. Disabling the Event Scheduler.",
+ MYF(ME_NOREFRESH));
/* Disable the scheduler since the system tables are not up to date */
- opt_event_scheduler= EVENTS_DISABLED;
+ opt_event_scheduler= EVENTS_OFF;
goto end;
}
- /*
- Was disabled explicitly from the command line, or because we're running
- with --skip-grant-tables, or --bootstrap, or because we have no system
- tables.
- */
- if (opt_event_scheduler == Events::EVENTS_DISABLED)
- goto end;
-
DBUG_ASSERT(opt_event_scheduler == Events::EVENTS_ON ||
opt_event_scheduler == Events::EVENTS_OFF);
@@ -897,20 +911,20 @@ Events::init(bool opt_noacl_or_bootstrap)
if (event_queue->init_queue(thd) || load_events_from_db(thd) ||
(opt_event_scheduler == EVENTS_ON && scheduler->start(&err_no)))
{
- sql_print_error("Event Scheduler: Error while loading from disk.");
+ my_message_sql(ER_STARTUP,
+ "Event Scheduler: Error while loading from mysql.event table.",
+ MYF(ME_NOREFRESH));
res= TRUE; /* fatal error: request unireg_abort */
goto end;
}
Event_worker_thread::init(db_repository);
+ inited= 1;
end:
if (res)
- {
- delete db_repository;
- delete event_queue;
- delete scheduler;
- }
- delete thd;
+ deinit();
+ if (!had_thd)
+ delete thd;
DBUG_RETURN(res);
}
@@ -930,17 +944,14 @@ Events::deinit()
{
DBUG_ENTER("Events::deinit");
- if (opt_event_scheduler != EVENTS_DISABLED)
- {
- delete scheduler;
- scheduler= NULL; /* safety */
- delete event_queue;
- event_queue= NULL; /* safety */
- }
-
+ delete scheduler;
+ scheduler= NULL; /* For restart */
+ delete event_queue;
+ event_queue= NULL; /* For restart */
delete db_repository;
- db_repository= NULL; /* safety */
+ db_repository= NULL; /* For restart */
+ inited= 0;
DBUG_VOID_RETURN;
}
@@ -1043,7 +1054,7 @@ Events::dump_internal_status()
holding LOCK_global_system_variables.
*/
mysql_mutex_lock(&LOCK_global_system_variables);
- if (opt_event_scheduler == EVENTS_DISABLED)
+ if (!inited)
puts("The Event Scheduler is disabled");
else
{
@@ -1057,11 +1068,13 @@ Events::dump_internal_status()
bool Events::start(int *err_no)
{
+ DBUG_ASSERT(inited);
return scheduler->start(err_no);
}
bool Events::stop()
{
+ DBUG_ASSERT(inited);
return scheduler->stop();
}
@@ -1091,7 +1104,6 @@ Events::load_events_from_db(THD *thd)
bool ret= TRUE;
uint count= 0;
ulong saved_master_access;
-
DBUG_ENTER("Events::load_events_from_db");
DBUG_PRINT("enter", ("thd: 0x%lx", (long) thd));
@@ -1116,7 +1128,9 @@ Events::load_events_from_db(THD *thd)
if (ret)
{
- sql_print_error("Event Scheduler: Failed to open table mysql.event");
+ my_message_sql(ER_STARTUP,
+ "Event Scheduler: Failed to open table mysql.event",
+ MYF(ME_NOREFRESH));
DBUG_RETURN(TRUE);
}
@@ -1138,9 +1152,11 @@ Events::load_events_from_db(THD *thd)
if (et->load_from_row(thd, table))
{
- sql_print_error("Event Scheduler: "
- "Error while loading events from mysql.event. "
- "The table probably contains bad data or is corrupted");
+ my_message(ER_STARTUP,
+ "Event Scheduler: "
+ "Error while loading events from mysql.event. "
+ "The table probably contains bad data or is corrupted",
+ MYF(ME_NOREFRESH));
delete et;
goto end;
}
@@ -1177,9 +1193,12 @@ Events::load_events_from_db(THD *thd)
}
}
}
- if (global_system_variables.log_warnings)
- sql_print_information("Event Scheduler: Loaded %d event%s",
- count, (count == 1) ? "" : "s");
+ my_printf_error(ER_STARTUP,
+ "Event Scheduler: Loaded %d event%s",
+ MYF(ME_NOREFRESH |
+ (global_system_variables.log_warnings) ?
+ ME_JUST_INFO: 0),
+ count, (count == 1) ? "" : "s");
ret= FALSE;
end:
diff --git a/sql/events.h b/sql/events.h
index bc2af1fb4de..368aa9a05d5 100644
--- a/sql/events.h
+++ b/sql/events.h
@@ -79,9 +79,11 @@ public:
and the @@global.event_scheduler SQL variable.
See sys_var.cc
*/
- enum enum_opt_event_scheduler { EVENTS_OFF, EVENTS_ON, EVENTS_DISABLED };
+ enum enum_opt_event_scheduler { EVENTS_OFF, EVENTS_ON, EVENTS_DISABLED,
+ EVENTS_ORIGINAL };
/* Protected using LOCK_global_system_variables only. */
- static ulong opt_event_scheduler;
+ static ulong opt_event_scheduler, startup_state;
+ static ulong inited;
static bool check_if_system_tables_error();
static bool start(int *err_no);
static bool stop();
@@ -91,8 +93,7 @@ public:
static Event_db_repository *
get_db_repository() { return db_repository; }
- static bool
- init(bool opt_noacl);
+ static bool init(THD *thd, bool opt_noacl);
static void
deinit();
@@ -130,6 +131,11 @@ public:
static void
dump_internal_status();
+ static void set_original_state(ulong startup_state_org)
+ {
+ startup_state= startup_state_org;
+ }
+
private:
static bool
@@ -139,8 +145,6 @@ private:
static Event_queue *event_queue;
static Event_scheduler *scheduler;
static Event_db_repository *db_repository;
- /* Set to TRUE if an error at start up */
- static bool check_system_tables_error;
private:
/* Prevent use of these */
diff --git a/sql/filesort.cc b/sql/filesort.cc
index ef91e227928..917b9de6038 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -25,7 +25,6 @@
#include <my_global.h>
#include "sql_priv.h"
#include "filesort.h"
-#include "unireg.h" // REQUIRED by other includes
#ifdef HAVE_STDDEF_H
#include <stddef.h> /* for macro offsetof */
#endif
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 043f7fb280b..0e009e76066 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -5271,6 +5271,7 @@ err:
{
(void) m_file[j]->ha_index_end();
}
+ destroy_record_priority_queue();
}
DBUG_RETURN(error);
}
diff --git a/sql/handler.cc b/sql/handler.cc
index 0f341a0ccc5..193d36a1122 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -5113,7 +5113,7 @@ bool Discovered_table_list::add_table(const char *tname, size_t tlen)
custom discover_table_names() method, that calls add_table() directly).
Note: avoid comparing the same name twice (here and in add_file).
*/
- if (wild && my_wildcmp(files_charset_info, tname, tname + tlen, wild, wend,
+ if (wild && my_wildcmp(table_alias_charset, tname, tname + tlen, wild, wend,
wild_prefix, wild_one, wild_many))
return 0;
diff --git a/sql/hostname.cc b/sql/hostname.cc
index 656663a9692..6aef84f1b26 100644
--- a/sql/hostname.cc
+++ b/sql/hostname.cc
@@ -26,6 +26,7 @@
*/
#include <my_global.h>
#include "sql_priv.h"
+#include "unireg.h" // SPECIAL_NO_HOST_CACHE
#include "hostname.h"
#include "unireg.h"
#ifndef __WIN__
diff --git a/sql/item.cc b/sql/item.cc
index a1a91007a0a..0f10ccbd88c 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -21,7 +21,6 @@
#endif
#include <my_global.h> /* NO_EMBEDDED_ACCESS_CHECKS */
#include "sql_priv.h"
-#include "unireg.h" // REQUIRED: for other includes
#include <mysql.h>
#include <m_ctype.h>
#include "my_dir.h"
@@ -4676,8 +4675,24 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference)
As this is an outer field it should be added to the list of
non aggregated fields of the outer select.
*/
- marker= select->cur_pos_in_select_list;
- select->join->non_agg_fields.push_back(this, thd->mem_root);
+ if (select->join)
+ {
+ marker= select->cur_pos_in_select_list;
+ select->join->non_agg_fields.push_back(this, thd->mem_root);
+ }
+ else
+ {
+ /*
+ join is absent if it is upper SELECT_LEX of non-select
+ command
+ */
+ DBUG_ASSERT(select->master_unit()->outer_select() == NULL &&
+ (thd->lex->sql_command != SQLCOM_SELECT &&
+ thd->lex->sql_command != SQLCOM_UPDATE_MULTI &&
+ thd->lex->sql_command != SQLCOM_DELETE_MULTI &&
+ thd->lex->sql_command != SQLCOM_INSERT_SELECT &&
+ thd->lex->sql_command != SQLCOM_REPLACE_SELECT));
+ }
}
if (*from_field != view_ref_found)
{
@@ -6582,6 +6597,7 @@ Item *Item_field::update_value_transformer(THD *thd, uchar *select_arg)
{
List<Item> *all_fields= &select->join->all_fields;
Item **ref_pointer_array= select->ref_pointer_array;
+ DBUG_ASSERT(all_fields->elements <= select->ref_pointer_array_size);
int el= all_fields->elements;
Item_ref *ref;
diff --git a/sql/item.h b/sql/item.h
index e662eed4a71..e262ce9d12d 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -25,7 +25,6 @@
#include "sql_priv.h" /* STRING_BUFFER_USUAL_SIZE */
#include "unireg.h"
#include "sql_const.h" /* RAND_TABLE_BIT, MAX_FIELD_NAME */
-#include "unireg.h" // REQUIRED: for other includes
#include "thr_malloc.h" /* sql_calloc */
#include "field.h" /* Derivation */
#include "sql_type.h"
@@ -4264,6 +4263,8 @@ public:
bool eq(const Item *item, bool binary_cmp) const;
Item *get_tmp_table_item(THD *thd)
{
+ if (const_item())
+ return copy_or_same(thd);
Item *item= Item_ref::get_tmp_table_item(thd);
item->name= name;
return item;
diff --git a/sql/key.cc b/sql/key.cc
index aaecbda57ad..1b00e951de0 100644
--- a/sql/key.cc
+++ b/sql/key.cc
@@ -18,7 +18,6 @@
#include <my_global.h>
#include "sql_priv.h"
-#include "unireg.h" // REQUIRED: by includes later
#include "key.h" // key_rec_cmp
#include "field.h" // Field
diff --git a/sql/lock.cc b/sql/lock.cc
index 7e7b378bfb4..2e44786d6fe 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -73,7 +73,6 @@
#include <my_global.h>
#include "sql_priv.h"
#include "debug_sync.h"
-#include "unireg.h" // REQUIRED: for other includes
#include "lock.h"
#include "sql_base.h" // close_tables_for_reopen
#include "sql_parse.h" // is_log_table_write_query
diff --git a/sql/log.cc b/sql/log.cc
index cea3d7e855e..ddf6bd07695 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -8013,12 +8013,14 @@ int MYSQL_BIN_LOG::wait_for_update_bin_log(THD* thd,
int ret= 0;
DBUG_ENTER("wait_for_update_bin_log");
+ thd_wait_begin(thd, THD_WAIT_BINLOG);
mysql_mutex_assert_owner(&LOCK_log);
if (!timeout)
mysql_cond_wait(&update_cond, &LOCK_log);
else
ret= mysql_cond_timedwait(&update_cond, &LOCK_log,
const_cast<struct timespec *>(timeout));
+ thd_wait_end(thd);
DBUG_RETURN(ret);
}
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index f9a3c2a0b3a..9dcf87adecb 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -5876,7 +5876,15 @@ int mysqld_main(int argc, char **argv)
execute_ddl_log_recovery();
- if (Events::init(opt_noacl || opt_bootstrap))
+ /*
+ Change EVENTS_ORIGINAL to EVENTS_OFF (the default value) as there is no
+ point in using ORIGINAL during startup
+ */
+ if (Events::opt_event_scheduler == Events::EVENTS_ORIGINAL)
+ Events::opt_event_scheduler= Events::EVENTS_OFF;
+
+ Events::set_original_state(Events::opt_event_scheduler);
+ if (Events::init((THD*) 0, opt_noacl || opt_bootstrap))
unireg_abort(1);
if (WSREP_ON)
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index e8cff9e69ab..f36887eb137 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -341,7 +341,8 @@ int opt_sum_query(THD *thd,
there are no outer joins.
*/
if (!conds && !((Item_sum_count*) item)->get_arg(0)->maybe_null &&
- !outer_tables && maybe_exact_count)
+ !outer_tables && maybe_exact_count &&
+ ((item->used_tables() & OUTER_REF_TABLE_BIT) == 0))
{
if (!is_exact_count)
{
@@ -369,7 +370,8 @@ int opt_sum_query(THD *thd,
indexes to find the key.
*/
Item *expr=item_sum->get_arg(0);
- if (expr->real_item()->type() == Item::FIELD_ITEM)
+ if (((expr->used_tables() & OUTER_REF_TABLE_BIT) == 0) &&
+ expr->real_item()->type() == Item::FIELD_ITEM)
{
uchar key_buff[MAX_KEY_LENGTH];
TABLE_REF ref;
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 249dd73e2df..fa42915f5a9 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -27,7 +27,6 @@
#include <my_global.h>
#include "sql_priv.h"
-#include "unireg.h" // REQUIRED: for other includes
#include "protocol.h"
#include "sql_class.h" // THD
#include <stdarg.h>
diff --git a/sql/records.cc b/sql/records.cc
index b6d68a5017f..ebda0ed35b0 100644
--- a/sql/records.cc
+++ b/sql/records.cc
@@ -66,10 +66,12 @@ static int rr_index_desc(READ_RECORD *info);
@param reverse Scan in the reverse direction
*/
-void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
+bool init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
bool print_error, uint idx, bool reverse)
{
int error;
+ DBUG_ENTER("init_read_record_idx");
+
empty_record(table);
bzero((char*) info,sizeof(*info));
info->thd= thd;
@@ -88,6 +90,7 @@ void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
/* read_record will be changed to rr_index in rr_index_first */
info->read_record= reverse ? rr_index_last : rr_index_first;
+ DBUG_RETURN(error != 0);
}
diff --git a/sql/records.h b/sql/records.h
index 21477d4a30b..a3f0b5eb084 100644
--- a/sql/records.h
+++ b/sql/records.h
@@ -76,7 +76,7 @@ public:
bool init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form,
SQL_SELECT *select, int use_record_cache,
bool print_errors, bool disable_rr_cache);
-void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
+bool init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
bool print_error, uint idx, bool reverse);
void end_read_record(READ_RECORD *info);
diff --git a/sql/rpl_injector.cc b/sql/rpl_injector.cc
index caa84d867ad..bff0da26862 100644
--- a/sql/rpl_injector.cc
+++ b/sql/rpl_injector.cc
@@ -15,7 +15,6 @@
#include <my_global.h>
#include "sql_priv.h"
-#include "unireg.h" // REQUIRED by later includes
#include "rpl_injector.h"
#include "transaction.h"
#include "sql_parse.h" // begin_trans, end_trans, COMMIT
diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc
index 02104af8cd3..216fbde0177 100644
--- a/sql/rpl_mi.cc
+++ b/sql/rpl_mi.cc
@@ -17,7 +17,6 @@
#include <my_global.h> // For HAVE_REPLICATION
#include "sql_priv.h"
#include <my_dir.h>
-#include "unireg.h" // REQUIRED by other includes
#include "rpl_mi.h"
#include "slave.h" // SLAVE_MAX_HEARTBEAT_PERIOD
#include "strfunc.h"
diff --git a/sql/rpl_record_old.cc b/sql/rpl_record_old.cc
index 061fab78dbd..5b876373b9c 100644
--- a/sql/rpl_record_old.cc
+++ b/sql/rpl_record_old.cc
@@ -15,7 +15,6 @@
#include <my_global.h>
#include "sql_priv.h"
-#include "unireg.h" // REQUIRED by other includes
#include "rpl_rli.h"
#include "rpl_record_old.h"
#include "log_event.h" // Log_event_type
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 679bd152a39..03fef5de866 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -2693,7 +2693,8 @@ static int check_alter_user(THD *thd, const char *host, const char *user)
}
if (IF_WSREP((!WSREP(thd) || !thd->wsrep_applier), 1) &&
- !thd->slave_thread && !thd->security_ctx->priv_user[0])
+ !thd->slave_thread && !thd->security_ctx->priv_user[0] &&
+ !in_bootstrap)
{
my_message(ER_PASSWORD_ANONYMOUS_USER,
ER_THD(thd, ER_PASSWORD_ANONYMOUS_USER),
@@ -9110,8 +9111,7 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
So we need to examine the current element once again, but
we don't need to restart the search from the beginning.
*/
- if (idx != elements)
- idx++;
+ idx++;
break;
}
@@ -9143,6 +9143,7 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
my_hash_update(roles_mappings_hash, (uchar*) role_grant_pair,
(uchar*) old_key, old_key_length);
+ idx++; // see the comment above
break;
}
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 1189a26f047..90ba0451e30 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -6455,6 +6455,7 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
*/
table_name && table_name[0] &&
(my_strcasecmp(table_alias_charset, table_list->alias, table_name) ||
+ (db_name && db_name[0] && (!table_list->db || !table_list->db[0])) ||
(db_name && db_name[0] && table_list->db && table_list->db[0] &&
(table_list->schema_table ?
my_strcasecmp(system_charset_info, db_name, table_list->db) :
@@ -6928,7 +6929,10 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter,
for (uint i= 0; (item=li++); i++)
{
- if (field_name && item->real_item()->type() == Item::FIELD_ITEM)
+ if (field_name &&
+ (item->real_item()->type() == Item::FIELD_ITEM ||
+ ((item->type() == Item::REF_ITEM) &&
+ (((Item_ref *)item)->ref_type() == Item_ref::VIEW_REF))))
{
Item_ident *item_field= (Item_ident*) item;
@@ -7054,35 +7058,6 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter,
break;
}
}
- else if (table_name && item->type() == Item::REF_ITEM &&
- ((Item_ref *)item)->ref_type() == Item_ref::VIEW_REF)
- {
- /*
- TODO:Here we process prefixed view references only. What we should
- really do is process all types of Item_ref's. But this will currently
- lead to a clash with the way references to outer SELECTs (from the
- HAVING clause) are handled in e.g. :
- SELECT 1 FROM t1 AS t1_o GROUP BY a
- HAVING (SELECT t1_o.a FROM t1 AS t1_i GROUP BY t1_i.a LIMIT 1).
- Processing all Item_ref's here will cause t1_o.a to resolve to itself.
- We still need to process the special case of Item_direct_view_ref
- because in the context of views they have the same meaning as
- Item_field for tables.
- */
- Item_ident *item_ref= (Item_ident *) item;
- if (field_name && item_ref->name && item_ref->table_name &&
- !my_strcasecmp(system_charset_info, item_ref->name, field_name) &&
- !my_strcasecmp(table_alias_charset, item_ref->table_name,
- table_name) &&
- (!db_name || (item_ref->db_name &&
- !strcmp (item_ref->db_name, db_name))))
- {
- found= li.ref();
- *counter= i;
- *resolution= RESOLVED_IGNORING_ALIAS;
- break;
- }
- }
}
if (!found)
{
diff --git a/sql/sql_base.h b/sql/sql_base.h
index 1c0029d9692..3a23e2ea218 100644
--- a/sql/sql_base.h
+++ b/sql/sql_base.h
@@ -16,7 +16,6 @@
#ifndef SQL_BASE_INCLUDED
#define SQL_BASE_INCLUDED
-#include "unireg.h" // REQUIRED: for other includes
#include "sql_trigger.h" /* trg_event_type */
#include "sql_class.h" /* enum_mark_columns */
#include "mysqld.h" /* key_map */
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 1bf48921998..e95e32a5e0b 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -30,7 +30,6 @@
#include <my_global.h> /* NO_EMBEDDED_ACCESS_CHECKS */
#include "sql_priv.h"
-#include "unireg.h" // REQUIRED: for other includes
#include "sql_class.h"
#include "sql_cache.h" // query_cache_abort
#include "sql_base.h" // close_thread_tables
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 2b62c462abc..aee6d560bfb 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -20,16 +20,14 @@
/* Classes in mysql */
-#include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */
-#ifdef MYSQL_SERVER
-#include "unireg.h" // REQUIRED: for other includes
-#endif
+#include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */
#include <waiting_threads.h>
#include "sql_const.h"
#include <mysql/plugin_audit.h>
#include "log.h"
#include "rpl_tblmap.h"
#include "mdl.h"
+#include "field.h" // Create_field
#include "probes_mysql.h"
#include "sql_locale.h" /* my_locale_st */
#include "sql_profile.h" /* PROFILING */
diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc
index f6e37f07e60..7821b96b9bb 100644
--- a/sql/sql_connect.cc
+++ b/sql/sql_connect.cc
@@ -28,7 +28,6 @@
#include "sql_audit.h"
#include "sql_connect.h"
#include "probes_mysql.h"
-#include "unireg.h" // REQUIRED: for other includes
#include "sql_parse.h" // sql_command_flags,
// execute_init_command,
// do_command
diff --git a/sql/sql_const.h b/sql/sql_const.h
index f856362f4e5..76e47bd278b 100644
--- a/sql/sql_const.h
+++ b/sql/sql_const.h
@@ -17,12 +17,14 @@
@file
File containing constants that can be used throughout the server.
- @note This file shall not contain any includes of any kinds.
+ @note This file shall not contain or include any declarations of any kinds.
*/
#ifndef SQL_CONST_INCLUDED
#define SQL_CONST_INCLUDED
+#include <mysql_version.h>
+
#define LIBLEN FN_REFLEN-FN_LEN /* Max l{ngd p} dev */
/* extra 4+4 bytes for slave tmp tables */
#define MAX_DBKEY_LENGTH (NAME_LEN*2+1+1+4+4)
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 8995684b8f6..f49a053918b 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -529,17 +529,18 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
free_underlaid_joins(thd, select_lex);
DBUG_RETURN(TRUE);
}
+
if (query_plan.index == MAX_KEY || (select && select->quick))
+ error= init_read_record(&info, thd, table, select, 1, 1, FALSE);
+ else
+ error= init_read_record_idx(&info, thd, table, 1, query_plan.index,
+ reverse);
+ if (error)
{
- if (init_read_record(&info, thd, table, select, 1, 1, FALSE))
- {
- delete select;
- free_underlaid_joins(thd, select_lex);
- DBUG_RETURN(TRUE);
- }
+ delete select;
+ free_underlaid_joins(thd, select_lex);
+ DBUG_RETURN(TRUE);
}
- else
- init_read_record_idx(&info, thd, table, 1, query_plan.index, reverse);
init_ftfuncs(thd, select_lex, 1);
THD_STAGE_INFO(thd, stage_updating);
diff --git a/sql/sql_digest.h b/sql/sql_digest.h
index ce159283d4d..eaf74b9542e 100644
--- a/sql/sql_digest.h
+++ b/sql/sql_digest.h
@@ -41,6 +41,9 @@ struct sql_digest_storage
For Example:
SELECT * FROM T1;
&lt;SELECT_TOKEN&gt; &lt;*&gt; &lt;FROM_TOKEN&gt; &lt;ID_TOKEN&gt; &lt;2&gt; &lt;T1&gt;
+
+ @note Only the first @c m_byte_count bytes are initialized,
+ out of @c m_token_array_length.
*/
unsigned char *m_token_array;
/* Length of the token array to be considered for DIGEST_TEXT calculation. */
@@ -63,10 +66,6 @@ struct sql_digest_storage
m_full= false;
m_byte_count= 0;
m_charset_number= 0;
- if (m_token_array_length > 0)
- {
- memset(m_token_array, 0, m_token_array_length);
- }
memset(m_md5, 0, MD5_HASH_SIZE);
}
diff --git a/sql/sql_error.cc b/sql/sql_error.cc
index 47f24ad9cb8..b72d642efbc 100644
--- a/sql/sql_error.cc
+++ b/sql/sql_error.cc
@@ -510,8 +510,10 @@ Diagnostics_area::set_error_status(uint sql_errno,
void
Diagnostics_area::disable_status()
{
+ DBUG_ENTER("disable_status");
DBUG_ASSERT(! is_set());
m_status= DA_DISABLED;
+ DBUG_VOID_RETURN;
}
Warning_info::Warning_info(ulonglong warn_id_arg,
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index 05e333e37fc..662fa33dc9f 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -55,7 +55,6 @@
#include <my_global.h>
#include "sql_priv.h"
#include "sql_handler.h"
-#include "unireg.h" // REQUIRED: for other includes
#include "sql_base.h" // close_thread_tables
#include "lock.h" // mysql_unlock_tables
#include "key.h" // key_copy
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 574e0892872..7a0a114971d 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -58,7 +58,6 @@
#include <my_global.h> /* NO_EMBEDDED_ACCESS_CHECKS */
#include "sql_priv.h"
-#include "unireg.h" // REQUIRED: for other includes
#include "sql_insert.h"
#include "sql_update.h" // compare_record
#include "sql_base.h" // close_thread_tables
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 3c4f99d1a7c..898e3ae33c6 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -20,7 +20,6 @@
#define MYSQL_LEX 1
#include <my_global.h>
#include "sql_priv.h"
-#include "unireg.h" // REQUIRED: for other includes
#include "sql_class.h" // sql_lex.h: SQLCOM_END
#include "sql_lex.h"
#include "sql_parse.h" // add_to_list
@@ -557,6 +556,16 @@ void lex_end(LEX *lex)
DBUG_ENTER("lex_end");
DBUG_PRINT("enter", ("lex: 0x%lx", (long) lex));
+ lex_end_stage1(lex);
+ lex_end_stage2(lex);
+
+ DBUG_VOID_RETURN;
+}
+
+void lex_end_stage1(LEX *lex)
+{
+ DBUG_ENTER("lex_end_stage1");
+
/* release used plugins */
if (lex->plugins.elements) /* No function call and no mutex if no plugins. */
{
@@ -580,6 +589,19 @@ void lex_end(LEX *lex)
lex->sphead= NULL;
}
+ DBUG_VOID_RETURN;
+}
+
+/*
+ MASTER INFO parameters (or state) is normally cleared towards the end
+ of a statement. But in case of PS, the state needs to be preserved during
+ its lifetime and should only be cleared on PS close or deallocation.
+*/
+void lex_end_stage2(LEX *lex)
+{
+ DBUG_ENTER("lex_end_stage2");
+
+ /* Reset LEX_MASTER_INFO */
lex->mi.reset(lex->sql_command == SQLCOM_CHANGE_MASTER);
DBUG_VOID_RETURN;
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index d39da819513..644d1a19cfd 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -3119,6 +3119,8 @@ extern void lex_init(void);
extern void lex_free(void);
extern void lex_start(THD *thd);
extern void lex_end(LEX *lex);
+extern void lex_end_stage1(LEX *lex);
+extern void lex_end_stage2(LEX *lex);
void end_lex_with_single_table(THD *thd, TABLE *table, LEX *old_lex);
int init_lex_with_single_table(THD *thd, TABLE *table, LEX *lex);
extern int MYSQLlex(union YYSTYPE *yylval, THD *thd);
diff --git a/sql/sql_manager.cc b/sql/sql_manager.cc
index c6c465aa4e2..8cf849b97d0 100644
--- a/sql/sql_manager.cc
+++ b/sql/sql_manager.cc
@@ -24,7 +24,6 @@
#include <my_global.h>
#include "sql_priv.h"
#include "sql_manager.h"
-#include "unireg.h" // REQUIRED: for other includes
#include "sql_base.h" // flush_tables
static bool volatile manager_thread_in_use;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 6c965cf8359..1388ec01459 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -17,7 +17,6 @@
#define MYSQL_LEX 1
#include <my_global.h>
#include "sql_priv.h"
-#include "unireg.h" // REQUIRED: for other includes
#include "sql_parse.h" // sql_kill, *_precheck, *_prepare
#include "lock.h" // try_transactional_lock,
// check_transactional_lock,
@@ -693,7 +692,7 @@ static char *fgets_fn(char *buffer, size_t size, fgets_input_t input, int *error
static void handle_bootstrap_impl(THD *thd)
{
MYSQL_FILE *file= bootstrap_file;
- DBUG_ENTER("handle_bootstrap");
+ DBUG_ENTER("handle_bootstrap_impl");
#ifndef EMBEDDED_LIBRARY
pthread_detach_this_thread();
@@ -6691,6 +6690,7 @@ bool check_fk_parent_table_access(THD *thd,
table_name.str= (char *) thd->memdup(fk_key->ref_table.str,
fk_key->ref_table.length+1);
table_name.length= my_casedn_str(files_charset_info, table_name.str);
+ db_name.length = my_casedn_str(files_charset_info, db_name.str);
}
parent_table.init_one_table(db_name.str, db_name.length,
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index 8e77d77205c..16588871fd8 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -49,7 +49,6 @@
#define MYSQL_LEX 1
#include <my_global.h>
#include "sql_priv.h"
-#include "unireg.h" // REQUIRED: for other includes
#include "sql_partition.h"
#include "key.h" // key_restore
#include "sql_parse.h" // parse_sql
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 2b37cb172aa..dfe6d1c2117 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -1419,7 +1419,8 @@ static int mysql_test_update(Prepared_statement *stmt,
(SELECT_ACL & ~table_list->table->grant.privilege);
table_list->register_want_access(SELECT_ACL);
#endif
- if (setup_fields(thd, 0, stmt->lex->value_list, MARK_COLUMNS_NONE, 0, 0))
+ if (setup_fields(thd, 0, stmt->lex->value_list, MARK_COLUMNS_NONE, 0, 0) ||
+ check_unique_table(thd, table_list))
goto error;
/* TODO: here we should send types of placeholders to the client. */
DBUG_RETURN(0);
@@ -3475,7 +3476,8 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
select_number_after_prepare= thd->select_number;
- lex_end(lex);
+ /* Preserve CHANGE MASTER attributes */
+ lex_end_stage1(lex);
cleanup_stmt();
thd->restore_backup_statement(this, &stmt_backup);
thd->stmt_arena= old_stmt_arena;
@@ -4102,6 +4104,10 @@ void Prepared_statement::deallocate()
{
/* We account deallocate in the same manner as mysqld_stmt_close */
status_var_increment(thd->status_var.com_stmt_close);
+
+ /* It should now be safe to reset CHANGE MASTER parameters */
+ lex_end_stage2(lex);
+
/* Statement map calls delete stmt on erase */
thd->stmt_map.erase(this);
}
diff --git a/sql/sql_profile.cc b/sql/sql_profile.cc
index bc11f5fdb21..48f7987daf5 100644
--- a/sql/sql_profile.cc
+++ b/sql/sql_profile.cc
@@ -31,7 +31,6 @@
#include <my_global.h>
#include "sql_priv.h"
-#include "unireg.h" // REQUIRED: for other includes
#include "sql_profile.h"
#include <my_sys.h>
#include "sql_show.h" // schema_table_store_record
diff --git a/sql/sql_reload.cc b/sql/sql_reload.cc
index e6c8e0777b8..7f2cf987f0e 100644
--- a/sql/sql_reload.cc
+++ b/sql/sql_reload.cc
@@ -94,6 +94,7 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options,
my_error(ER_UNKNOWN_ERROR, MYF(0));
}
}
+ opt_noacl= 0;
if (tmp_thd)
{
diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc
index d9cf0344cdf..17b297f63bd 100644
--- a/sql/sql_rename.cc
+++ b/sql/sql_rename.cc
@@ -274,8 +274,9 @@ do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db, char *new_table_name,
LEX_STRING table_name= { ren_table->table_name,
ren_table->table_name_length };
LEX_STRING new_table= { (char *) new_alias, strlen(new_alias) };
+ LEX_STRING new_db_name= { (char*)new_db, strlen(new_db)};
(void) rename_table_in_stat_tables(thd, &db_name, &table_name,
- &db_name, &new_table);
+ &new_db_name, &new_table);
if ((rc= Table_triggers_list::change_table_name(thd, ren_table->db,
old_alias,
ren_table->table_name,
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index bc5cf2df0ca..3b339368d0a 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -492,6 +492,7 @@ fix_inner_refs(THD *thd, List<Item> &all_fields, SELECT_LEX *select,
if (ref_pointer_array && !ref->found_in_select_list)
{
int el= all_fields.elements;
+ DBUG_ASSERT(all_fields.elements <= select->ref_pointer_array_size);
ref_pointer_array[el]= item;
/* Add the field item to the select list of the current select. */
all_fields.push_front(item, thd->mem_root);
@@ -907,6 +908,7 @@ JOIN::prepare(Item ***rref_pointer_array,
{
Item_field *field= new (thd->mem_root) Item_field(thd, *(Item_field**)ord->item);
int el= all_fields.elements;
+ DBUG_ASSERT(all_fields.elements <= select_lex->ref_pointer_array_size);
ref_pointer_array[el]= field;
all_fields.push_front(field, thd->mem_root);
ord->item= ref_pointer_array + el;
@@ -21980,6 +21982,8 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
return TRUE; /* Wrong field. */
uint el= all_fields.elements;
+ DBUG_ASSERT(all_fields.elements <=
+ thd->lex->current_select->ref_pointer_array_size);
/* Add new field to field list. */
all_fields.push_front(order_item, thd->mem_root);
ref_pointer_array[el]= order_item;
@@ -22240,6 +22244,8 @@ create_distinct_group(THD *thd, Item **ref_pointer_array,
*/
Item_field *new_item= new (thd->mem_root) Item_field(thd, (Item_field*)item);
int el= all_fields.elements;
+ DBUG_ASSERT(all_fields.elements <=
+ thd->lex->current_select->ref_pointer_array_size);
orig_ref_pointer_array[el]= new_item;
all_fields.push_front(new_item, thd->mem_root);
ord->item= orig_ref_pointer_array + el;
diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc
index 021e4c37e86..28e76ae43f1 100644
--- a/sql/sql_statistics.cc
+++ b/sql/sql_statistics.cc
@@ -592,6 +592,8 @@ public:
stat_file->extra(HA_EXTRA_FLUSH);
return FALSE;
}
+
+ friend class Stat_table_write_iter;
};
@@ -888,7 +890,7 @@ public:
@note
A value from the field min_value/max_value is always converted
- into a utf8 string. If the length of the column 'min_value'/'max_value'
+ into a varbinary string. If the length of the column 'min_value'/'max_value'
is less than the length of the string the string is trimmed to fit the
length of the column.
*/
@@ -896,7 +898,7 @@ public:
void store_stat_fields()
{
char buff[MAX_FIELD_WIDTH];
- String val(buff, sizeof(buff), &my_charset_utf8_bin);
+ String val(buff, sizeof(buff), &my_charset_bin);
for (uint i= COLUMN_STAT_MIN_VALUE; i <= COLUMN_STAT_HISTOGRAM; i++)
{
@@ -913,7 +915,7 @@ public:
else
{
table_field->collected_stats->min_value->val_str(&val);
- stat_field->store(val.ptr(), val.length(), &my_charset_utf8_bin);
+ stat_field->store(val.ptr(), val.length(), &my_charset_bin);
}
break;
case COLUMN_STAT_MAX_VALUE:
@@ -922,7 +924,7 @@ public:
else
{
table_field->collected_stats->max_value->val_str(&val);
- stat_field->store(val.ptr(), val.length(), &my_charset_utf8_bin);
+ stat_field->store(val.ptr(), val.length(), &my_charset_bin);
}
break;
case COLUMN_STAT_NULLS_RATIO:
@@ -983,7 +985,7 @@ public:
if (find_stat())
{
char buff[MAX_FIELD_WIDTH];
- String val(buff, sizeof(buff), &my_charset_utf8_bin);
+ String val(buff, sizeof(buff), &my_charset_bin);
for (uint i= COLUMN_STAT_MIN_VALUE; i <= COLUMN_STAT_HIST_TYPE; i++)
{
@@ -1002,12 +1004,12 @@ public:
case COLUMN_STAT_MIN_VALUE:
stat_field->val_str(&val);
table_field->read_stats->min_value->store(val.ptr(), val.length(),
- &my_charset_utf8_bin);
+ &my_charset_bin);
break;
case COLUMN_STAT_MAX_VALUE:
stat_field->val_str(&val);
table_field->read_stats->max_value->store(val.ptr(), val.length(),
- &my_charset_utf8_bin);
+ &my_charset_bin);
break;
case COLUMN_STAT_NULLS_RATIO:
table_field->read_stats->set_nulls_ratio(stat_field->val_real());
@@ -1053,7 +1055,7 @@ public:
if (find_stat())
{
char buff[MAX_FIELD_WIDTH];
- String val(buff, sizeof(buff), &my_charset_utf8_bin);
+ String val(buff, sizeof(buff), &my_charset_bin);
uint fldno= COLUMN_STAT_HISTOGRAM;
Field *stat_field= stat_table->field[fldno];
table_field->read_stats->set_not_null(fldno);
@@ -1264,6 +1266,117 @@ public:
};
+
+/*
+ An iterator to enumerate statistics table rows which allows to modify
+ the rows while reading them.
+
+ Used by RENAME TABLE handling to assign new dbname.tablename to statistic
+ rows.
+*/
+class Stat_table_write_iter
+{
+ Stat_table *owner;
+ IO_CACHE io_cache;
+ uchar *rowid_buf;
+ uint rowid_size;
+
+public:
+ Stat_table_write_iter(Stat_table *stat_table_arg)
+ : owner(stat_table_arg), rowid_buf(NULL),
+ rowid_size(owner->stat_file->ref_length)
+ {
+ my_b_clear(&io_cache);
+ }
+
+ /*
+ Initialize the iterator. It will return rows with n_keyparts matching the
+ curernt values.
+
+ @return false - OK
+ true - Error
+ */
+ bool init(uint n_keyparts)
+ {
+ if (!(rowid_buf= (uchar*)my_malloc(rowid_size, MYF(0))))
+ return true;
+
+ if (open_cached_file(&io_cache, mysql_tmpdir, TEMP_PREFIX,
+ 1024, MYF(MY_WME)))
+ return true;
+
+ handler *h= owner->stat_file;
+ uchar key[MAX_KEY_LENGTH];
+ uint prefix_len= 0;
+ for (uint i= 0; i < n_keyparts; i++)
+ prefix_len += owner->stat_key_info->key_part[i].store_length;
+
+ key_copy(key, owner->record[0], owner->stat_key_info,
+ prefix_len);
+ key_part_map prefix_map= (key_part_map) ((1 << n_keyparts) - 1);
+ h->ha_index_init(owner->stat_key_idx, false);
+ int res= h->ha_index_read_map(owner->record[0], key, prefix_map,
+ HA_READ_KEY_EXACT);
+ if (res)
+ {
+ reinit_io_cache(&io_cache, READ_CACHE, 0L, 0, 0);
+ /* "Key not found" is not considered an error */
+ return (res == HA_ERR_KEY_NOT_FOUND)? false: true;
+ }
+
+ do {
+ h->position(owner->record[0]);
+ my_b_write(&io_cache, h->ref, rowid_size);
+
+ } while (!h->ha_index_next_same(owner->record[0], key, prefix_len));
+
+ /* Prepare for reading */
+ reinit_io_cache(&io_cache, READ_CACHE, 0L, 0, 0);
+ h->ha_index_or_rnd_end();
+ if (h->ha_rnd_init(false))
+ return true;
+
+ return false;
+ }
+
+ /*
+ Read the next row.
+
+ @return
+ false OK
+ true No more rows or error.
+ */
+ bool get_next_row()
+ {
+ if (!my_b_inited(&io_cache) || my_b_read(&io_cache, rowid_buf, rowid_size))
+ return true; /* No more data */
+
+ handler *h= owner->stat_file;
+ /*
+ We should normally be able to find the row that we have rowid for. If we
+ don't, let's consider this an error.
+ */
+ int res= h->ha_rnd_pos(owner->record[0], rowid_buf);
+
+ return (res==0)? false : true;
+ }
+
+ void cleanup()
+ {
+ if (rowid_buf)
+ my_free(rowid_buf);
+ rowid_buf= NULL;
+ owner->stat_file->ha_index_or_rnd_end();
+ close_cached_file(&io_cache);
+ my_b_clear(&io_cache);
+ }
+
+ ~Stat_table_write_iter()
+ {
+ cleanup();
+ }
+};
+
/*
Histogram_builder is a helper class that is used to build histograms
for columns
@@ -3285,25 +3398,34 @@ int rename_table_in_stat_tables(THD *thd, LEX_STRING *db, LEX_STRING *tab,
stat_table= tables[INDEX_STAT].table;
Index_stat index_stat(stat_table, db, tab);
index_stat.set_full_table_name();
- while (index_stat.find_next_stat_for_prefix(2))
+
+ Stat_table_write_iter index_iter(&index_stat);
+ if (index_iter.init(2))
+ rc= 1;
+ while (!index_iter.get_next_row())
{
err= index_stat.update_table_name_key_parts(new_db, new_tab);
if (err & !rc)
rc= 1;
index_stat.set_full_table_name();
}
+ index_iter.cleanup();
/* Rename table in the statistical table column_stats */
stat_table= tables[COLUMN_STAT].table;
Column_stat column_stat(stat_table, db, tab);
column_stat.set_full_table_name();
- while (column_stat.find_next_stat_for_prefix(2))
+ Stat_table_write_iter column_iter(&column_stat);
+ if (column_iter.init(2))
+ rc= 1;
+ while (!column_iter.get_next_row())
{
err= column_stat.update_table_name_key_parts(new_db, new_tab);
if (err & !rc)
rc= 1;
column_stat.set_full_table_name();
}
+ column_iter.cleanup();
/* Rename table in the statistical table table_stats */
stat_table= tables[TABLE_STAT].table;
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 35d736ea8a3..5af13273130 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -5848,6 +5848,13 @@ drop_create_field:
{
if (!key->if_not_exists() && !key->or_replace())
continue;
+
+ /* Check if the table already has a PRIMARY KEY */
+ bool dup_primary_key= key->type == Key::PRIMARY &&
+ table->s->primary_key != MAX_KEY;
+ if (dup_primary_key)
+ goto remove_key;
+
/* If the name of the key is not specified, */
/* let us check the name of the first key part. */
if ((keyname= key->name.str) == NULL)
@@ -5915,8 +5922,8 @@ remove_key:
if (key->if_not_exists())
{
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
- ER_DUP_KEYNAME, ER_THD(thd, ER_DUP_KEYNAME),
- keyname);
+ ER_DUP_KEYNAME, ER_THD(thd, dup_primary_key
+ ? ER_MULTIPLE_PRI_KEY : ER_DUP_KEYNAME), keyname);
key_it.remove();
if (key->type == Key::FOREIGN_KEY)
{
diff --git a/sql/sql_time.cc b/sql/sql_time.cc
index ccba3d16575..9785a1691af 100644
--- a/sql/sql_time.cc
+++ b/sql/sql_time.cc
@@ -19,7 +19,6 @@
#include <my_global.h>
#include "sql_priv.h"
-#include "unireg.h" // REQUIRED by other includes
#include "sql_time.h"
#include "tztime.h" // struct Time_zone
#include "sql_class.h" // THD
diff --git a/sql/sql_trigger.h b/sql/sql_trigger.h
index 52892550d35..7dfe8939945 100644
--- a/sql/sql_trigger.h
+++ b/sql/sql_trigger.h
@@ -17,6 +17,8 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+#include <mysqld_error.h>
+
/* Forward declarations */
class Item_trigger_field;
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 7a66cc3734c..0caae7ac821 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -22,7 +22,6 @@
#include <my_global.h> /* NO_EMBEDDED_ACCESS_CHECKS */
#include "sql_priv.h"
-#include "unireg.h" // REQUIRED: for other includes
#include "sql_update.h"
#include "sql_cache.h" // query_cache_*
#include "sql_base.h" // close_tables_for_reopen
@@ -366,6 +365,9 @@ int mysql_update(THD *thd,
DBUG_RETURN(1); /* purecov: inspected */
}
+ if (check_unique_table(thd, table_list))
+ DBUG_RETURN(TRUE);
+
/* Apply the IN=>EXISTS transformation to all subqueries and optimize them. */
if (select_lex->optimize_unflattened_subqueries(false))
DBUG_RETURN(TRUE);
@@ -460,7 +462,8 @@ int mysql_update(THD *thd,
query_plan.scanned_rows= select? select->records: table->file->stats.records;
if (select && select->quick && select->quick->unique_key_range())
- { // Single row select (always "ordered"): Ok to use with key field UPDATE
+ {
+ /* Single row select (always "ordered"): Ok to use with key field UPDATE */
need_sort= FALSE;
query_plan.index= MAX_KEY;
used_key_is_modified= FALSE;
@@ -469,7 +472,8 @@ int mysql_update(THD *thd,
{
ha_rows scanned_limit= query_plan.scanned_rows;
query_plan.index= get_index_for_order(order, table, select, limit,
- &scanned_limit, &need_sort, &reverse);
+ &scanned_limit, &need_sort,
+ &reverse);
if (!need_sort)
query_plan.scanned_rows= scanned_limit;
@@ -482,12 +486,15 @@ int mysql_update(THD *thd,
else
{
if (need_sort)
- { // Assign table scan index to check below for modified key fields:
+ {
+ /* Assign table scan index to check below for modified key fields: */
query_plan.index= table->file->key_used_on_scan;
}
if (query_plan.index != MAX_KEY)
- { // Check if we are modifying a key that we are used to search with:
- used_key_is_modified= is_key_used(table, query_plan.index, table->write_set);
+ {
+ /* Check if we are modifying a key that we are used to search with: */
+ used_key_is_modified= is_key_used(table, query_plan.index,
+ table->write_set);
}
}
}
@@ -604,19 +611,20 @@ int mysql_update(THD *thd,
B. query_plan.index != MAX_KEY
B.1 quick select is used, start the scan with init_read_record
B.2 quick select is not used, this is full index scan (with LIMIT)
- Full index scan must be started with init_read_record_idx
+ Full index scan must be started with init_read_record_idx
*/
if (query_plan.index == MAX_KEY || (select && select->quick))
+ error= init_read_record(&info, thd, table, select, 0, 1, FALSE);
+ else
+ error= init_read_record_idx(&info, thd, table, 1, query_plan.index,
+ reverse);
+
+ if (error)
{
- if (init_read_record(&info, thd, table, select, 0, 1, FALSE))
- {
- close_cached_file(&tempfile);
- goto err;
- }
+ close_cached_file(&tempfile);
+ goto err;
}
- else
- init_read_record_idx(&info, thd, table, 1, query_plan.index, reverse);
THD_STAGE_INFO(thd, stage_searching_rows_for_update);
ha_rows tmp_limit= limit;
@@ -1115,19 +1123,30 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
setup_ftfuncs(select_lex))
DBUG_RETURN(TRUE);
- /* Check that we are not using table that we are updating in a sub select */
- {
- TABLE_LIST *duplicate;
- if ((duplicate= unique_table(thd, table_list, table_list->next_global, 0)))
- {
- update_non_unique_table_error(table_list, "UPDATE", duplicate);
- DBUG_RETURN(TRUE);
- }
- }
select_lex->fix_prepare_information(thd, conds, &fake_conds);
DBUG_RETURN(FALSE);
}
+/**
+ Check that we are not using table that we are updating in a sub select
+
+ @param thd Thread handle
+ @param table_list List of table with first to check
+
+ @retval TRUE Error
+ @retval FALSE OK
+*/
+bool check_unique_table(THD *thd, TABLE_LIST *table_list)
+{
+ TABLE_LIST *duplicate;
+ DBUG_ENTER("check_unique_table");
+ if ((duplicate= unique_table(thd, table_list, table_list->next_global, 0)))
+ {
+ update_non_unique_table_error(table_list, "UPDATE", duplicate);
+ DBUG_RETURN(TRUE);
+ }
+ DBUG_RETURN(FALSE);
+}
/***************************************************************************
Update multiple tables from join
diff --git a/sql/sql_update.h b/sql/sql_update.h
index 64029c5d634..4c6f89d8468 100644
--- a/sql/sql_update.h
+++ b/sql/sql_update.h
@@ -27,6 +27,7 @@ typedef class st_select_lex_unit SELECT_LEX_UNIT;
bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
Item **conds, uint order_num, ORDER *order);
+bool check_unique_table(THD *thd, TABLE_LIST *table_list);
int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields,
List<Item> &values,COND *conds,
uint order_num, ORDER *order, ha_rows limit,
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index b240958898c..85189fa481f 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -1532,6 +1532,11 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
*/
lex->sql_command= old_lex->sql_command;
lex->duplicates= old_lex->duplicates;
+
+ /* Fields in this view can be used in upper select in case of merge. */
+ if (table->select_lex)
+ table->select_lex->select_n_where_fields+=
+ lex->select_lex.select_n_where_fields;
}
/*
This method has a dependency on the proper lock type being set,
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 6f05a2c6d9e..a5a62aeeafb 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -35,7 +35,6 @@
#define Select Lex->current_select
#include <my_global.h>
#include "sql_priv.h"
-#include "unireg.h" // REQUIRED: for other includes
#include "sql_parse.h" /* comp_*_creator */
#include "sql_table.h" /* primary_key_name */
#include "sql_partition.h" /* mem_alloc_error, partition_info, HASH_PARTITION */
@@ -10909,6 +10908,15 @@ table_factor:
sel->add_joined_table($$);
lex->pop_context();
lex->nest_level--;
+ /*
+ Fields in derived table can be used in upper select in
+ case of merge. We do not add HAVING fields because we do
+ not merge such derived. We do not add union because
+ also do not merge them
+ */
+ if (!sel->next_select())
+ $2->select_n_where_fields+=
+ sel->select_n_where_fields;
}
/*else if (($3->select_lex &&
$3->select_lex->master_unit()->is_union() &&
@@ -15418,6 +15426,9 @@ current_role:
grant_role:
ident_or_text
{
+ CHARSET_INFO *cs= system_charset_info;
+ /* trim end spaces (as they'll be lost in mysql.user anyway) */
+ $1.length= cs->cset->lengthsp(cs, $1.str, $1.length);
if ($1.length == 0)
{
my_error(ER_INVALID_ROLE, MYF(0), "");
@@ -15433,7 +15444,7 @@ grant_role:
if (check_string_char_length(&$$->user, ER_USERNAME,
username_char_length,
- system_charset_info, 0))
+ cs, 0))
MYSQL_YYABORT;
}
| current_role
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 682d8039478..b3900dd5208 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -839,30 +839,26 @@ static Sys_var_ulong Sys_delayed_queue_size(
VALID_RANGE(1, UINT_MAX), DEFAULT(DELAYED_QUEUE_SIZE), BLOCK_SIZE(1));
#ifdef HAVE_EVENT_SCHEDULER
-static const char *event_scheduler_names[]= { "OFF", "ON", "DISABLED", NullS };
+static const char *event_scheduler_names[]= { "OFF", "ON", "DISABLED",
+ "ORIGINAL", NullS };
static bool event_scheduler_check(sys_var *self, THD *thd, set_var *var)
{
- /* DISABLED is only accepted on the command line */
- if (var->save_result.ulonglong_value == Events::EVENTS_DISABLED)
- return true;
- /*
- If the scheduler was disabled because there are no/bad
- system tables, produce a more meaningful error message
- than ER_OPTION_PREVENTS_STATEMENT
- */
- if (Events::check_if_system_tables_error())
- return true;
if (Events::opt_event_scheduler == Events::EVENTS_DISABLED)
{
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0),
"--event-scheduler=DISABLED or --skip-grant-tables");
return true;
}
+ /* DISABLED is only accepted on the command line */
+ if (var->save_result.ulonglong_value == Events::EVENTS_DISABLED)
+ return true;
return false;
}
+
static bool event_scheduler_update(sys_var *self, THD *thd, enum_var_type type)
{
int err_no= 0;
+ bool ret;
uint opt_event_scheduler_value= Events::opt_event_scheduler;
mysql_mutex_unlock(&LOCK_global_system_variables);
/*
@@ -881,9 +877,25 @@ static bool event_scheduler_update(sys_var *self, THD *thd, enum_var_type type)
rare and it's difficult to avoid it without opening up possibilities
for deadlocks. See bug#51160.
*/
- bool ret= opt_event_scheduler_value == Events::EVENTS_ON
- ? Events::start(&err_no)
- : Events::stop();
+
+ /* EVENTS_ORIGINAL means we should revert back to the startup state */
+ if (opt_event_scheduler_value == Events::EVENTS_ORIGINAL)
+ {
+ opt_event_scheduler_value= Events::opt_event_scheduler=
+ Events::startup_state;
+ }
+
+ /*
+ If the scheduler was not properly inited (because of wrong system tables),
+ try to init it again. This is needed for mysql_upgrade to work properly if
+ the event tables where upgraded.
+ */
+ if (!Events::inited && (Events::init(thd, 0) || !Events::inited))
+ ret= 1;
+ else
+ ret= opt_event_scheduler_value == Events::EVENTS_ON ?
+ Events::start(&err_no) :
+ Events::stop();
mysql_mutex_lock(&LOCK_global_system_variables);
if (ret)
{
@@ -3388,7 +3400,7 @@ static char *server_version_compile_machine_ptr;
static Sys_var_charptr Sys_version_compile_machine(
"version_compile_machine", "version_compile_machine",
READ_ONLY GLOBAL_VAR(server_version_compile_machine_ptr),
- CMD_LINE_HELP_ONLY, IN_SYSTEM_CHARSET, DEFAULT(MACHINE_TYPE));
+ CMD_LINE_HELP_ONLY, IN_SYSTEM_CHARSET, DEFAULT(DEFAULT_MACHINE));
static char *server_version_compile_os_ptr;
static Sys_var_charptr Sys_version_compile_os(
diff --git a/sql/table.cc b/sql/table.cc
index 9c90e5026b8..6dedd2f8acc 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -19,7 +19,6 @@
#include <my_global.h> /* NO_EMBEDDED_ACCESS_CHECKS */
#include "sql_priv.h"
-#include "unireg.h" // REQUIRED: for other includes
#include "table.h"
#include "key.h" // find_ref_key
#include "sql_table.h" // build_table_filename,