summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2016-06-30 16:38:05 +0200
committerSergei Golubchik <serg@mariadb.org>2016-06-30 16:38:05 +0200
commit932646b1ff6a8f5815a961340a9e1ee4702f5b44 (patch)
tree5bc42ace8ae1f7e4d00baffd468bdb7564e851f1 /sql
parent0bb30f3603b519780eaf3fe0527b1c6af285229a (diff)
parent33492ec8d4e2077cf8e07d0628a959d8729bd1f9 (diff)
downloadmariadb-git-932646b1ff6a8f5815a961340a9e1ee4702f5b44.tar.gz
Merge branch '10.1' into 10.2
Diffstat (limited to 'sql')
-rw-r--r--sql/contributors.h2
-rw-r--r--sql/create_options.cc15
-rw-r--r--sql/create_options.h6
-rw-r--r--sql/debug_sync.h1
-rw-r--r--sql/encryption.cc16
-rw-r--r--sql/field.cc78
-rw-r--r--sql/field.h33
-rw-r--r--sql/gen_lex_hash.cc2
-rw-r--r--sql/handler.cc128
-rw-r--r--sql/handler.h34
-rw-r--r--sql/item.cc28
-rw-r--r--sql/item.h4
-rw-r--r--sql/item_cmpfunc.cc52
-rw-r--r--sql/item_cmpfunc.h15
-rw-r--r--sql/item_func.cc2
-rw-r--r--sql/item_func.h6
-rw-r--r--sql/item_geofunc.cc5
-rw-r--r--sql/item_geofunc.h6
-rw-r--r--sql/item_strfunc.cc12
-rw-r--r--sql/item_subselect.cc78
-rw-r--r--sql/item_subselect.h34
-rw-r--r--sql/item_timefunc.cc6
-rw-r--r--sql/lex.h3
-rw-r--r--sql/log.cc2
-rw-r--r--sql/log.h4
-rw-r--r--sql/log_event.cc63
-rw-r--r--sql/log_event_old.cc52
-rw-r--r--sql/mem_root_array.h67
-rw-r--r--sql/mysqld.cc21
-rw-r--r--sql/mysqld.h15
-rw-r--r--sql/opt_range.cc116
-rw-r--r--sql/opt_range_mrr.cc26
-rw-r--r--sql/opt_subselect.cc9
-rw-r--r--sql/share/errmsg-utf8.txt6
-rw-r--r--sql/slave.cc15
-rw-r--r--sql/slave.h4
-rw-r--r--sql/sp_head.cc10
-rw-r--r--sql/sql_acl.cc179
-rw-r--r--sql/sql_admin.cc37
-rw-r--r--sql/sql_base.cc3
-rw-r--r--sql/sql_class.cc61
-rw-r--r--sql/sql_class.h14
-rw-r--r--sql/sql_connect.cc3
-rw-r--r--sql/sql_help.cc11
-rw-r--r--sql/sql_insert.cc46
-rw-r--r--sql/sql_lex.cc29
-rw-r--r--sql/sql_load.cc5
-rw-r--r--sql/sql_locale.cc2
-rw-r--r--sql/sql_locale.h2
-rw-r--r--sql/sql_parse.cc54
-rw-r--r--sql/sql_parse.h3
-rw-r--r--sql/sql_plugin.h2
-rw-r--r--sql/sql_priv.h2
-rw-r--r--sql/sql_reload.cc3
-rw-r--r--sql/sql_select.cc219
-rw-r--r--sql/sql_select.h2
-rw-r--r--sql/sql_show.cc24
-rw-r--r--sql/sql_statistics.cc9
-rw-r--r--sql/sql_table.cc25
-rw-r--r--sql/sql_update.cc16
-rw-r--r--sql/sql_yacc.yy1112
-rw-r--r--sql/sys_vars.cc11
-rw-r--r--sql/sys_vars.ic1
-rw-r--r--sql/table.cc34
-rw-r--r--sql/threadpool_unix.cc6
-rw-r--r--sql/winservice.c13
-rw-r--r--sql/wsrep_applier.h2
-rw-r--r--sql/wsrep_binlog.h8
-rw-r--r--sql/wsrep_mysqld.cc15
-rw-r--r--sql/wsrep_mysqld.h5
-rw-r--r--sql/wsrep_priv.h8
-rw-r--r--sql/wsrep_sst.cc1
-rw-r--r--sql/wsrep_utils.h3
-rw-r--r--sql/wsrep_var.cc11
74 files changed, 1676 insertions, 1281 deletions
diff --git a/sql/contributors.h b/sql/contributors.h
index 04f8b74aa65..76674d654e5 100644
--- a/sql/contributors.h
+++ b/sql/contributors.h
@@ -46,7 +46,7 @@ struct show_table_contributors_st show_table_contributors[]= {
/* Smaller sponsors, newer per year */
{"Verkkokauppa.com", "Finland", "Sponsor of the MariaDB Foundation"},
- {"Webyog", "Bangalore", "Sponsor of the MariaDB Foundation"},
+ {"Virtuozzo", "https://virtuozzo.com/", "Sponsor of the MariaDB Foundation"},
/* Sponsors of important features */
{"Google", "USA", "Sponsoring encryption, parallel replication and GTID"},
diff --git a/sql/create_options.cc b/sql/create_options.cc
index 3011c4b2d7e..40382c7887e 100644
--- a/sql/create_options.cc
+++ b/sql/create_options.cc
@@ -685,20 +685,25 @@ uchar *engine_table_options_frm_image(uchar *buff,
@returns pointer to byte after last recorded in the buffer
*/
-uchar *engine_option_value::frm_read(const uchar *buff, engine_option_value **start,
+uchar *engine_option_value::frm_read(const uchar *buff, const uchar *buff_end,
+ engine_option_value **start,
engine_option_value **end, MEM_ROOT *root)
{
LEX_STRING name, value;
uint len;
+#define need_buff(N) if (buff + (N) >= buff_end) return NULL
+ need_buff(3);
name.length= buff[0];
buff++;
+ need_buff(name.length + 2);
if (!(name.str= strmake_root(root, (const char*)buff, name.length)))
return NULL;
buff+= name.length;
len= uint2korr(buff);
value.length= len & ~FRM_QUOTED_VALUE;
buff+= 2;
+ need_buff(value.length);
if (!(value.str= strmake_root(root, (const char*)buff, value.length)))
return NULL;
buff+= value.length;
@@ -735,8 +740,8 @@ bool engine_table_options_frm_read(const uchar *buff, uint length,
while (buff < buff_end && *buff)
{
- if (!(buff= engine_option_value::frm_read(buff, &share->option_list, &end,
- root)))
+ if (!(buff= engine_option_value::frm_read(buff, buff_end,
+ &share->option_list, &end, root)))
DBUG_RETURN(TRUE);
}
buff++;
@@ -745,7 +750,7 @@ bool engine_table_options_frm_read(const uchar *buff, uint length,
{
while (buff < buff_end && *buff)
{
- if (!(buff= engine_option_value::frm_read(buff,
+ if (!(buff= engine_option_value::frm_read(buff, buff_end,
&share->field[count]->option_list,
&end, root)))
DBUG_RETURN(TRUE);
@@ -757,7 +762,7 @@ bool engine_table_options_frm_read(const uchar *buff, uint length,
{
while (buff < buff_end && *buff)
{
- if (!(buff= engine_option_value::frm_read(buff,
+ if (!(buff= engine_option_value::frm_read(buff, buff_end,
&share->key_info[count].option_list,
&end, root)))
DBUG_RETURN(TRUE);
diff --git a/sql/create_options.h b/sql/create_options.h
index eb21f291ff4..3e7f9ecfabf 100644
--- a/sql/create_options.h
+++ b/sql/create_options.h
@@ -23,7 +23,8 @@
#define SQL_CREATE_OPTIONS_INCLUDED
#include "sql_class.h"
-//#include "handler.h"
+
+enum { ENGINE_OPTION_MAX_LENGTH=32767 };
class engine_option_value: public Sql_alloc
{
@@ -66,7 +67,8 @@ class engine_option_value: public Sql_alloc
link(start, end);
}
}
- static uchar *frm_read(const uchar *buff, engine_option_value **start,
+ static uchar *frm_read(const uchar *buff, const uchar *buff_end,
+ engine_option_value **start,
engine_option_value **end, MEM_ROOT *root);
void link(engine_option_value **start, engine_option_value **end);
uint frm_length();
diff --git a/sql/debug_sync.h b/sql/debug_sync.h
index 339a21139b1..999667b9efc 100644
--- a/sql/debug_sync.h
+++ b/sql/debug_sync.h
@@ -44,7 +44,6 @@ extern void debug_sync_end(void);
extern void debug_sync_init_thread(THD *thd);
extern void debug_sync_end_thread(THD *thd);
extern bool debug_sync_set_action(THD *thd, const char *action_str, size_t len);
-
extern bool debug_sync_update(THD *thd, char *val_str, size_t len);
extern uchar *debug_sync_value_ptr(THD *thd);
diff --git a/sql/encryption.cc b/sql/encryption.cc
index 209b092b0a4..52aaef896dd 100644
--- a/sql/encryption.cc
+++ b/sql/encryption.cc
@@ -23,6 +23,8 @@
static plugin_ref encryption_manager= 0;
struct encryption_service_st encryption_handler;
+extern "C" {
+
uint no_key(uint)
{
return ENCRYPTION_KEY_VERSION_INVALID;
@@ -41,6 +43,8 @@ static unsigned int get_length(unsigned int slen, unsigned int key_id,
return my_aes_get_size(MY_AES_CBC, slen);
}
+} /* extern "C" */
+
int initialize_encryption_plugin(st_plugin_int *plugin)
{
if (encryption_manager)
@@ -57,9 +61,15 @@ int initialize_encryption_plugin(st_plugin_int *plugin)
st_mariadb_encryption *handle=
(struct st_mariadb_encryption*) plugin->plugin->info;
- encryption_handler.encryption_ctx_size_func=
- handle->crypt_ctx_size ? handle->crypt_ctx_size :
- (uint (*)(unsigned int, unsigned int))my_aes_ctx_size;
+ /*
+ Copmiler on Spark doesn't like the '?' operator here as it
+ belives the (uint (*)...) implies the C++ call model.
+ */
+ if (handle->crypt_ctx_size)
+ encryption_handler.encryption_ctx_size_func= handle->crypt_ctx_size;
+ else
+ encryption_handler.encryption_ctx_size_func=
+ (uint (*)(unsigned int, unsigned int))my_aes_ctx_size;
encryption_handler.encryption_ctx_init_func=
handle->crypt_ctx_init ? handle->crypt_ctx_init : ctx_init;
diff --git a/sql/field.cc b/sql/field.cc
index 36a5daaa165..c684e6a8046 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -1503,10 +1503,12 @@ Value_source::Converter_string_to_number::check_edom_and_truncation(THD *thd,
*/
-int Field_num::check_edom_and_truncation(const char *type, bool edom,
- CHARSET_INFO *cs,
- const char *str, uint length,
- const char *end)
+int Field_num::check_edom_and_important_data_truncation(const char *type,
+ bool edom,
+ CHARSET_INFO *cs,
+ const char *str,
+ uint length,
+ const char *end)
{
/* Test if we get an empty string or garbage */
if (edom)
@@ -1521,12 +1523,23 @@ int Field_num::check_edom_and_truncation(const char *type, bool edom,
set_warning(WARN_DATA_TRUNCATED, 1);
return 2;
}
- if (end < str + length)
- set_note(WARN_DATA_TRUNCATED, 1);
return 0;
}
+int Field_num::check_edom_and_truncation(const char *type, bool edom,
+ CHARSET_INFO *cs,
+ const char *str, uint length,
+ const char *end)
+{
+ int rc= check_edom_and_important_data_truncation(type, edom,
+ cs, str, length, end);
+ if (!rc && end < str + length)
+ set_note(WARN_DATA_TRUNCATED, 1);
+ return rc;
+}
+
+
/*
Conver a string to an integer then check bounds.
@@ -2050,6 +2063,7 @@ Field_str::Field_str(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
if (charset_arg->state & MY_CS_BINSORT)
flags|=BINARY_FLAG;
field_derivation= DERIVATION_IMPLICIT;
+ field_repertoire= my_charset_repertoire(charset_arg);
}
@@ -3048,7 +3062,8 @@ void Field_new_decimal::set_value_on_overflow(my_decimal *decimal_value,
If it does, stores the decimal in the buffer using binary format.
Otherwise sets maximal number that can be stored in the field.
- @param decimal_value my_decimal
+ @param decimal_value my_decimal
+ @param [OUT] native_error the error returned by my_decimal2binary().
@retval
0 ok
@@ -3056,7 +3071,8 @@ void Field_new_decimal::set_value_on_overflow(my_decimal *decimal_value,
1 error
*/
-bool Field_new_decimal::store_value(const my_decimal *decimal_value)
+bool Field_new_decimal::store_value(const my_decimal *decimal_value,
+ int *native_error)
{
ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
int error= 0;
@@ -3085,11 +3101,14 @@ bool Field_new_decimal::store_value(const my_decimal *decimal_value)
}
#endif
- if (warn_if_overflow(my_decimal2binary(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW,
- decimal_value, ptr, precision, dec)))
+ *native_error= my_decimal2binary(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW,
+ decimal_value, ptr, precision, dec);
+
+ if (*native_error == E_DEC_OVERFLOW)
{
my_decimal buff;
DBUG_PRINT("info", ("overflow"));
+ set_warning(ER_WARN_DATA_OUT_OF_RANGE, 1);
set_value_on_overflow(&buff, decimal_value->sign());
my_decimal2binary(E_DEC_FATAL_ERROR, &buff, ptr, precision, dec);
error= 1;
@@ -3100,6 +3119,16 @@ bool Field_new_decimal::store_value(const my_decimal *decimal_value)
}
+bool Field_new_decimal::store_value(const my_decimal *decimal_value)
+{
+ int native_error;
+ bool rc= store_value(decimal_value, &native_error);
+ if (!rc && native_error == E_DEC_TRUNCATED)
+ set_note(WARN_DATA_TRUNCATED, 1);
+ return rc;
+}
+
+
int Field_new_decimal::store(const char *from, uint length,
CHARSET_INFO *charset_arg)
{
@@ -3127,9 +3156,10 @@ int Field_new_decimal::store(const char *from, uint length,
if (thd->count_cuted_fields)
{
- if (check_edom_and_truncation("decimal",
- err && err != E_DEC_TRUNCATED,
- charset_arg, from, length, end))
+ if (check_edom_and_important_data_truncation("decimal",
+ err && err != E_DEC_TRUNCATED,
+ charset_arg,
+ from, length, end))
{
if (!thd->abort_on_warning)
{
@@ -3152,12 +3182,6 @@ int Field_new_decimal::store(const char *from, uint length,
}
DBUG_RETURN(1);
}
- /*
- E_DEC_TRUNCATED means minor truncation '1e-1000000000000' -> 0.0
- A note should be enough.
- */
- if (err == E_DEC_TRUNCATED)
- set_note(WARN_DATA_TRUNCATED, 1);
}
#ifndef DBUG_OFF
@@ -3165,7 +3189,21 @@ int Field_new_decimal::store(const char *from, uint length,
DBUG_PRINT("enter", ("value: %s",
dbug_decimal_as_string(dbug_buff, &decimal_value)));
#endif
- store_value(&decimal_value);
+ int err2;
+ if (store_value(&decimal_value, &err2))
+ DBUG_RETURN(1);
+
+ /*
+ E_DEC_TRUNCATED means minor truncation, a note should be enough:
+ - in err: str2my_decimal() truncated '1e-1000000000000' to 0.0
+ - in err2: store_value() truncated 1.123 to 1.12, e.g. for DECIMAL(10,2)
+ Also, we send a note if a string had some trailing spaces: '1.12 '
+ */
+ if (thd->count_cuted_fields &&
+ (err == E_DEC_TRUNCATED ||
+ err2 == E_DEC_TRUNCATED ||
+ end < from + length))
+ set_note(WARN_DATA_TRUNCATED, 1);
DBUG_RETURN(0);
}
diff --git a/sql/field.h b/sql/field.h
index 08d125d051b..afc9efab57c 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -1260,11 +1260,12 @@ public:
{ return binary() ? &my_charset_bin : charset(); }
virtual CHARSET_INFO *sort_charset(void) const { return charset(); }
virtual bool has_charset(void) const { return FALSE; }
- virtual void set_charset(CHARSET_INFO *charset_arg) { }
virtual enum Derivation derivation(void) const
{ return DERIVATION_IMPLICIT; }
virtual uint repertoire(void) const { return MY_REPERTOIRE_UNICODE30; }
- virtual void set_derivation(enum Derivation derivation_arg) { }
+ virtual void set_derivation(enum Derivation derivation_arg,
+ uint repertoire_arg)
+ { }
virtual int set_time() { return 1; }
bool set_warning(Sql_condition::enum_warning_level, unsigned int code,
int cuted_increment) const;
@@ -1517,6 +1518,10 @@ protected:
class Field_num :public Field {
protected:
+ int check_edom_and_important_data_truncation(const char *type, bool edom,
+ CHARSET_INFO *cs,
+ const char *str, uint length,
+ const char *end_of_num);
int check_edom_and_truncation(const char *type, bool edom,
CHARSET_INFO *cs,
const char *str, uint length,
@@ -1594,8 +1599,10 @@ public:
class Field_str :public Field {
protected:
+ // TODO-10.2: Reuse DTCollation instead of these three members
CHARSET_INFO *field_charset;
enum Derivation field_derivation;
+ uint field_repertoire;
public:
bool can_be_substituted_to_equal_item(const Context &ctx,
const Item_equal *item_equal);
@@ -1619,15 +1626,15 @@ public:
{
return store(str, length, &my_charset_bin);
}
- uint repertoire(void) const
- {
- return my_charset_repertoire(field_charset);
- }
+ uint repertoire(void) const { return field_repertoire; }
CHARSET_INFO *charset(void) const { return field_charset; }
- void set_charset(CHARSET_INFO *charset_arg) { field_charset= charset_arg; }
enum Derivation derivation(void) const { return field_derivation; }
- virtual void set_derivation(enum Derivation derivation_arg)
- { field_derivation= derivation_arg; }
+ void set_derivation(enum Derivation derivation_arg,
+ uint repertoire_arg)
+ {
+ field_derivation= derivation_arg;
+ field_repertoire= repertoire_arg;
+ }
bool binary() const { return field_charset == &my_charset_bin; }
uint32 max_display_length() { return field_length; }
friend class Create_field;
@@ -1815,6 +1822,7 @@ public:
}
int reset(void);
bool store_value(const my_decimal *decimal_value);
+ bool store_value(const my_decimal *decimal_value, int *native_error);
void set_value_on_overflow(my_decimal *decimal_value, bool sign);
int store(const char *to, uint length, CHARSET_INFO *charset);
int store(double nr);
@@ -3172,10 +3180,9 @@ public:
packlength= 4;
if (set_packlength)
{
- uint32 l_char_length= len_arg/cs->mbmaxlen;
- packlength= l_char_length <= 255 ? 1 :
- l_char_length <= 65535 ? 2 :
- l_char_length <= 16777215 ? 3 : 4;
+ packlength= len_arg <= 255 ? 1 :
+ len_arg <= 65535 ? 2 :
+ len_arg <= 16777215 ? 3 : 4;
}
}
Field_blob(uint32 packlength_arg)
diff --git a/sql/gen_lex_hash.cc b/sql/gen_lex_hash.cc
index c37f4f145cf..3a3273d279b 100644
--- a/sql/gen_lex_hash.cc
+++ b/sql/gen_lex_hash.cc
@@ -310,6 +310,7 @@ void print_find_structs()
add_structs_to_map(root_by_len,max_len);
set_links(root_by_len,max_len);
print_hash_map("sql_functions_map");
+ free(hash_map);
hash_map= 0;
size_hash_map= 0;
@@ -319,6 +320,7 @@ void print_find_structs()
add_structs_to_map(root_by_len2,max_len2);
set_links(root_by_len2,max_len2);
print_hash_map("symbols_map");
+ free(hash_map);
}
diff --git a/sql/handler.cc b/sql/handler.cc
index d3ad6a085d2..3fbd1b3a71a 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -1,5 +1,5 @@
-/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
- Copyright (c) 2009, 2013, Monty Program Ab.
+/* Copyright (c) 2000, 2016, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2016, 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
@@ -4196,6 +4196,7 @@ handler::check_if_supported_inplace_alter(TABLE *altered_table,
Alter_inplace_info::ALTER_COLUMN_DEFAULT |
Alter_inplace_info::ALTER_COLUMN_OPTION |
Alter_inplace_info::CHANGE_CREATE_OPTION |
+ Alter_inplace_info::ALTER_PARTITIONED |
Alter_inplace_info::ALTER_RENAME;
/* Is there at least one operation that requires copy algorithm? */
@@ -6113,26 +6114,42 @@ int ha_abort_transaction(THD *bf_thd, THD *victim_thd, my_bool signal)
void ha_fake_trx_id(THD *thd)
{
DBUG_ENTER("ha_fake_trx_id");
+
+ bool no_fake_trx_id= true;
+
if (!WSREP(thd))
{
DBUG_VOID_RETURN;
}
- THD_TRANS *trans= &thd->transaction.all;
+ /* Try statement transaction if standard one is not set. */
+ THD_TRANS *trans= (thd->transaction.all.ha_list) ? &thd->transaction.all :
+ &thd->transaction.stmt;
+
Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
for (; ha_info; ha_info= ha_info_next)
{
handlerton *hton= ha_info->ht();
- if (!hton->fake_trx_id)
+ if (hton->fake_trx_id)
{
- WSREP_WARN("cannot get fake InnoDB transaction ID");
- }
- else
hton->fake_trx_id(hton, thd);
+
+ /* Got a fake trx id. */
+ no_fake_trx_id= false;
+
+ /*
+ We need transaction ID from just one storage engine providing
+ fake_trx_id (which will most likely be the case).
+ */
+ break;
+ }
ha_info_next= ha_info->next();
- ha_info->reset(); /* keep it conveniently zero-filled */
}
+
+ if (unlikely(no_fake_trx_id))
+ WSREP_WARN("Cannot get fake transaction ID from storage engine.");
+
DBUG_VOID_RETURN;
}
#endif /* WITH_WSREP */
@@ -6326,3 +6343,98 @@ bool HA_CREATE_INFO::check_conflicting_charset_declarations(CHARSET_INFO *cs)
}
return false;
}
+
+/* Remove all indexes for a given table from global index statistics */
+
+static
+int del_global_index_stats_for_table(THD *thd, uchar* cache_key, uint cache_key_length)
+{
+ int res = 0;
+ DBUG_ENTER("del_global_index_stats_for_table");
+
+ mysql_mutex_lock(&LOCK_global_index_stats);
+
+ for (uint i= 0; i < global_index_stats.records;)
+ {
+ INDEX_STATS *index_stats =
+ (INDEX_STATS*) my_hash_element(&global_index_stats, i);
+
+ /* We search correct db\0table_name\0 string */
+ if (index_stats &&
+ index_stats->index_name_length >= cache_key_length &&
+ !memcmp(index_stats->index, cache_key, cache_key_length))
+ {
+ res= my_hash_delete(&global_index_stats, (uchar*)index_stats);
+ /*
+ In our HASH implementation on deletion one elements
+ is moved into a place where a deleted element was,
+ and the last element is moved into the empty space.
+ Thus we need to re-examine the current element, but
+ we don't have to restart the search from the beginning.
+ */
+ }
+ else
+ i++;
+ }
+
+ mysql_mutex_unlock(&LOCK_global_index_stats);
+ DBUG_RETURN(res);
+}
+
+/* Remove a table from global table statistics */
+
+int del_global_table_stat(THD *thd, LEX_STRING *db, LEX_STRING *table)
+{
+ TABLE_STATS *table_stats;
+ int res = 0;
+ uchar *cache_key;
+ uint cache_key_length;
+ DBUG_ENTER("del_global_table_stat");
+
+ cache_key_length= db->length + 1 + table->length + 1;
+
+ if(!(cache_key= (uchar *)my_malloc(cache_key_length,
+ MYF(MY_WME | MY_ZEROFILL))))
+ {
+ /* Out of memory error already given */
+ res = 1;
+ goto end;
+ }
+
+ memcpy(cache_key, db->str, db->length);
+ memcpy(cache_key + db->length + 1, table->str, table->length);
+
+ res= del_global_index_stats_for_table(thd, cache_key, cache_key_length);
+
+ mysql_mutex_lock(&LOCK_global_table_stats);
+
+ if((table_stats= (TABLE_STATS*) my_hash_search(&global_table_stats,
+ cache_key,
+ cache_key_length)))
+ res= my_hash_delete(&global_table_stats, (uchar*)table_stats);
+
+ my_free(cache_key);
+ mysql_mutex_unlock(&LOCK_global_table_stats);
+
+end:
+ DBUG_RETURN(res);
+}
+
+/* Remove a index from global index statistics */
+
+int del_global_index_stat(THD *thd, TABLE* table, KEY* key_info)
+{
+ INDEX_STATS *index_stats;
+ uint key_length= table->s->table_cache_key.length + key_info->name_length + 1;
+ int res = 0;
+ DBUG_ENTER("del_global_index_stat");
+ mysql_mutex_lock(&LOCK_global_index_stats);
+
+ if((index_stats= (INDEX_STATS*) my_hash_search(&global_index_stats,
+ key_info->cache_name,
+ key_length)))
+ res= my_hash_delete(&global_index_stats, (uchar*)index_stats);
+
+ mysql_mutex_unlock(&LOCK_global_index_stats);
+ DBUG_RETURN(res);
+}
diff --git a/sql/handler.h b/sql/handler.h
index 56c2c87dfd7..cae95ea4ae6 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -1,8 +1,8 @@
#ifndef HANDLER_INCLUDED
#define HANDLER_INCLUDED
/*
- Copyright (c) 2000, 2014, Oracle and/or its affiliates.
- Copyright (c) 2009, 2014, Monty Program Ab.
+ Copyright (c) 2000, 2016, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2016, MariaDB
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -130,7 +130,7 @@ enum enum_alter_inplace_result {
*/
#define HA_PRIMARY_KEY_REQUIRED_FOR_POSITION (1ULL << 16)
#define HA_CAN_RTREEKEYS (1ULL << 17)
-#define HA_NOT_DELETE_WITH_CACHE (1ULL << 18)
+#define HA_NOT_DELETE_WITH_CACHE (1ULL << 18) /* unused */
/*
The following is we need to a primary key to delete (and update) a row.
If there is no primary key, all columns needs to be read on update and delete
@@ -144,7 +144,7 @@ enum enum_alter_inplace_result {
#define HA_HAS_OLD_CHECKSUM (1ULL << 24)
/* Table data are stored in separate files (for lower_case_table_names) */
#define HA_FILE_BASED (1ULL << 26)
-#define HA_NO_VARCHAR (1ULL << 27)
+#define HA_NO_VARCHAR (1ULL << 27) /* unused */
#define HA_CAN_BIT_FIELD (1ULL << 28) /* supports bit fields */
#define HA_NEED_READ_RANGE_BUFFER (1ULL << 29) /* for read_multi_range */
#define HA_ANY_INDEX_MAY_BE_UNIQUE (1ULL << 30)
@@ -249,6 +249,15 @@ enum enum_alter_inplace_result {
*/
#define HA_CAN_EXPORT (1LL << 45)
+/*
+ Storage engine does not require an exclusive metadata lock
+ on the table during optimize. (TODO and repair?).
+ It can allow other connections to open the table.
+ (it does not necessarily mean that other connections can
+ read or modify the table - this is defined by THR locks and the
+ ::store_lock() method).
+*/
+#define HA_CONCURRENT_OPTIMIZE (1LL << 46)
/*
Set of all binlog flags. Currently only contain the capabilities
@@ -407,7 +416,9 @@ static const uint MYSQL_START_TRANS_OPT_READ_WRITE = 4;
/* Flags for method is_fatal_error */
#define HA_CHECK_DUP_KEY 1
#define HA_CHECK_DUP_UNIQUE 2
+#define HA_CHECK_FK_ERROR 4
#define HA_CHECK_DUP (HA_CHECK_DUP_KEY + HA_CHECK_DUP_UNIQUE)
+#define HA_CHECK_ALL (~0U)
enum legacy_db_type
{
@@ -1935,7 +1946,10 @@ public:
// Virtual columns changed
static const HA_ALTER_FLAGS ALTER_COLUMN_VCOL = 1L << 30;
- // ALTER TABLE for a partitioned table
+ /**
+ ALTER TABLE for a partitioned table. The engine needs to commit
+ online alter of all partitions atomically (using group_commit_ctx)
+ */
static const HA_ALTER_FLAGS ALTER_PARTITIONED = 1L << 31;
static const HA_ALTER_FLAGS ALTER_ADD_CHECK_CONSTRAINT = 1LL << 32;
@@ -2953,7 +2967,10 @@ public:
((flags & HA_CHECK_DUP_KEY) &&
(error == HA_ERR_FOUND_DUPP_KEY ||
error == HA_ERR_FOUND_DUPP_UNIQUE)) ||
- error == HA_ERR_AUTOINC_ERANGE)
+ error == HA_ERR_AUTOINC_ERANGE ||
+ ((flags & HA_CHECK_FK_ERROR) &&
+ (error == HA_ERR_ROW_IS_REFERENCED ||
+ error == HA_ERR_NO_REFERENCED_ROW)))
return FALSE;
return TRUE;
}
@@ -4300,4 +4317,7 @@ inline const char *table_case_name(HA_CREATE_INFO *info, const char *name)
void print_keydup_error(TABLE *table, KEY *key, const char *msg, myf errflag);
void print_keydup_error(TABLE *table, KEY *key, myf errflag);
-#endif
+
+int del_global_index_stat(THD *thd, TABLE* table, KEY* key_info);
+int del_global_table_stat(THD *thd, LEX_STRING *db, LEX_STRING *table);
+#endif /* HANDLER_INCLUDED */
diff --git a/sql/item.cc b/sql/item.cc
index 99034d849ec..65b8cf25c9b 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2000, 2014, Oracle and/or its affiliates.
+ Copyright (c) 2000, 2016, Oracle and/or its affiliates.
Copyright (c) 2010, 2016, MariaDB
This program is free software; you can redistribute it and/or modify
@@ -202,9 +202,6 @@ bool Item::get_time_with_conversion(THD *thd, MYSQL_TIME *ltime,
*/
String *Item::val_str_ascii(String *str)
{
- if (!(collation.collation->state & MY_CS_NONASCII))
- return val_str(str);
-
DBUG_ASSERT(str != &str_value);
uint errors;
@@ -212,11 +209,15 @@ String *Item::val_str_ascii(String *str)
if (!res)
return 0;
- if ((null_value= str->copy(res->ptr(), res->length(),
- collation.collation, &my_charset_latin1,
- &errors)))
- return 0;
-
+ if (!(res->charset()->state & MY_CS_NONASCII))
+ str= res;
+ else
+ {
+ if ((null_value= str->copy(res->ptr(), res->length(), collation.collation,
+ &my_charset_latin1, &errors)))
+ return 0;
+ }
+
return str;
}
@@ -1246,8 +1247,8 @@ Item *Item_param::safe_charset_converter(THD *thd, CHARSET_INFO *tocs)
to it's possible that the converter will not be needed at all:
PREPARE stmt FROM 'SELECT * FROM t1 WHERE field = ?';
- SET @@arg= 1;
- EXECUTE stms USING @arg;
+ SET @arg= 1;
+ EXECUTE stmt USING @arg;
In the above example result_type is STRING_RESULT at prepare time,
and INT_RESULT at execution time.
@@ -3783,7 +3784,7 @@ Item_param::eq(const Item *item, bool binary_cmp) const
void Item_param::print(String *str, enum_query_type query_type)
{
- if (state == NO_VALUE)
+ if (state == NO_VALUE || query_type & QT_NO_DATA_EXPANSION)
{
str->append('?');
}
@@ -6716,7 +6717,8 @@ Item *Item_field::update_value_transformer(THD *thd, uchar *select_arg)
void Item_field::print(String *str, enum_query_type query_type)
{
- if (field && field->table->const_table)
+ if (field && field->table->const_table &&
+ !(query_type & QT_NO_DATA_EXPANSION))
{
print_value(str);
return;
diff --git a/sql/item.h b/sql/item.h
index 31d87b9f8e4..e5b71eb1845 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -2590,7 +2590,7 @@ public:
max_length= 0;
name= name_par ? name_par : (char*) "NULL";
fixed= 1;
- collation.set(cs, DERIVATION_IGNORABLE);
+ collation.set(cs, DERIVATION_IGNORABLE, MY_REPERTOIRE_ASCII);
}
enum Type type() const { return NULL_ITEM; }
bool eq(const Item *item, bool binary_cmp) const { return null_eq(item); }
@@ -5126,7 +5126,7 @@ public:
bool basic_const_item() const
{ return MY_TEST(example && example->basic_const_item()); }
virtual void clear() { null_value= TRUE; value_cached= FALSE; }
- bool is_null() { return null_value; }
+ bool is_null() { return !has_value(); }
virtual bool is_expensive()
{
if (value_cached)
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 2d38e705b0a..eafb6b1c91b 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -120,10 +120,11 @@ static int cmp_row_type(Item* item1, Item* item2)
static int agg_cmp_type(Item_result *type, Item **items, uint nitems)
{
- uint i;
+ uint unsigned_count= items[0]->unsigned_flag;
type[0]= items[0]->cmp_type();
- for (i= 1 ; i < nitems ; i++)
+ for (uint i= 1 ; i < nitems ; i++)
{
+ unsigned_count+= items[i]->unsigned_flag;
type[0]= item_cmp_type(type[0], items[i]);
/*
When aggregating types of two row expressions we have to check
@@ -135,6 +136,12 @@ static int agg_cmp_type(Item_result *type, Item **items, uint nitems)
if (type[0] == ROW_RESULT && cmp_row_type(items[0], items[i]))
return 1; // error found: invalid usage of rows
}
+ /**
+ If all arguments are of INT type but have different unsigned_flag values,
+ switch to DECIMAL_RESULT.
+ */
+ if (type[0] == INT_RESULT && unsigned_count != nitems && unsigned_count != 0)
+ type[0]= DECIMAL_RESULT;
return 0;
}
@@ -2328,10 +2335,7 @@ bool Item_func_ifnull::date_op(MYSQL_TIME *ltime, uint fuzzydate)
DBUG_ASSERT(fixed == 1);
if (!args[0]->get_date_with_conversion(ltime, fuzzydate & ~TIME_FUZZY_DATES))
return (null_value= false);
- if (!args[1]->get_date_with_conversion(ltime, fuzzydate & ~TIME_FUZZY_DATES))
- return (null_value= false);
- bzero((char*) ltime,sizeof(*ltime));
- return null_value= !(fuzzydate & TIME_FUZZY_DATES);
+ return (null_value= args[1]->get_date_with_conversion(ltime, fuzzydate & ~TIME_FUZZY_DATES));
}
@@ -2497,6 +2501,23 @@ void Item_func_nullif::split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array,
}
+bool Item_func_nullif::walk(Item_processor processor,
+ bool walk_subquery, void *arg)
+{
+ /*
+ No needs to iterate through args[2] when it's just a copy of args[0].
+ See MDEV-9712 Performance degradation of nested NULLIF
+ */
+ uint tmp_count= arg_count == 2 || args[0] == args[2] ? 2 : 3;
+ for (uint i= 0; i < tmp_count; i++)
+ {
+ if (args[i]->walk(processor, walk_subquery, arg))
+ return true;
+ }
+ return (this->*processor)(arg);
+}
+
+
void Item_func_nullif::update_used_tables()
{
if (m_cache)
@@ -2507,7 +2528,14 @@ void Item_func_nullif::update_used_tables()
}
else
{
- Item_func::update_used_tables();
+ /*
+ MDEV-9712 Performance degradation of nested NULLIF
+ No needs to iterate through args[2] when it's just a copy of args[0].
+ */
+ DBUG_ASSERT(arg_count == 3);
+ used_tables_and_const_cache_init();
+ used_tables_and_const_cache_update_and_join(args[0] == args[2] ? 2 : 3,
+ args);
}
}
@@ -3361,16 +3389,12 @@ double Item_func_coalesce::real_op()
bool Item_func_coalesce::date_op(MYSQL_TIME *ltime,uint fuzzydate)
{
DBUG_ASSERT(fixed == 1);
- null_value= 0;
for (uint i= 0; i < arg_count; i++)
{
- bool res= args[i]->get_date_with_conversion(ltime,
- fuzzydate & ~TIME_FUZZY_DATES);
- if (!args[i]->null_value)
- return res;
+ if (!args[i]->get_date_with_conversion(ltime, fuzzydate & ~TIME_FUZZY_DATES))
+ return (null_value= false);
}
- bzero((char*) ltime,sizeof(*ltime));
- return null_value|= !(fuzzydate & TIME_FUZZY_DATES);
+ return (null_value= true);
}
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index c1140b61efb..3285b5c6d50 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -1028,6 +1028,7 @@ public:
String *str_op(String *str);
my_decimal *decimal_op(my_decimal *);
void fix_length_and_dec();
+ bool walk(Item_processor processor, bool walk_subquery, void *arg);
uint decimal_precision() const { return args[2]->decimal_precision(); }
const char *func_name() const { return "nullif"; }
void print(String *str, enum_query_type query_type);
@@ -1039,13 +1040,21 @@ public:
Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond)
{
Context cmpctx(ANY_SUBST, cmp.compare_type(), cmp.compare_collation());
+ const Item *old0= args[0];
args[0]->propagate_equal_fields_and_change_item_tree(thd, cmpctx,
cond, &args[0]);
args[1]->propagate_equal_fields_and_change_item_tree(thd, cmpctx,
cond, &args[1]);
- args[2]->propagate_equal_fields_and_change_item_tree(thd,
- Context_identity(),
- cond, &args[2]);
+ /*
+ MDEV-9712 Performance degradation of nested NULLIF
+ ANY_SUBST is more relaxed than IDENTITY_SUBST.
+ If ANY_SUBST did not change args[0],
+ then we can skip propagation for args[2].
+ */
+ if (old0 != args[0])
+ args[2]->propagate_equal_fields_and_change_item_tree(thd,
+ Context_identity(),
+ cond, &args[2]);
return this;
}
};
diff --git a/sql/item_func.cc b/sql/item_func.cc
index c98630e0431..7f8c89cc228 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -6246,6 +6246,8 @@ bool Item_func_match::fix_index()
for (i=1; i < arg_count; i++)
{
+ if (args[i]->type() != FIELD_ITEM)
+ goto err;
item=(Item_field*)args[i];
for (keynr=0 ; keynr < fts ; keynr++)
{
diff --git a/sql/item_func.h b/sql/item_func.h
index 474f7b802c0..8316bb72c7d 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -1,7 +1,7 @@
#ifndef ITEM_FUNC_INCLUDED
#define ITEM_FUNC_INCLUDED
-/* Copyright (c) 2000, 2014, Oracle and/or its affiliates.
- Copyright (c) 2009, 2014, MariaDB
+/* Copyright (c) 2000, 2016, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2016, 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
@@ -209,7 +209,7 @@ public:
char buf[256];
String str(buf, sizeof(buf), system_charset_info);
str.length(0);
- print(&str, QT_ORDINARY);
+ print(&str, QT_NO_DATA_EXPANSION);
my_error(ER_DATA_OUT_OF_RANGE, MYF(0), type_name, str.c_ptr_safe());
}
inline double raise_float_overflow()
diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc
index 39d06fd7a26..bc4bde575b0 100644
--- a/sql/item_geofunc.cc
+++ b/sql/item_geofunc.cc
@@ -1,6 +1,5 @@
-/*
- Copyright (c) 2003-2007 MySQL AB, 2009, 2010 Sun Microsystems, Inc.
- Use is subject to license terms.
+/* Copyright (c) 2003, 2016, Oracle and/or its affiliates.
+ Copyright (c) 2011, 2016, 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
diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h
index 5a0a26ea779..93d52013e89 100644
--- a/sql/item_geofunc.h
+++ b/sql/item_geofunc.h
@@ -1,8 +1,8 @@
#ifndef ITEM_GEOFUNC_INCLUDED
#define ITEM_GEOFUNC_INCLUDED
-/* Copyright (c) 2000, 2010 Oracle and/or its affiliates.
- Copyright (C) 2011, 2015 MariaDB
+/* Copyright (c) 2000, 2016 Oracle and/or its affiliates.
+ Copyright (C) 2011, 2016, 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
@@ -259,7 +259,7 @@ public:
if (args[i]->fixed && args[i]->field_type() != MYSQL_TYPE_GEOMETRY)
{
String str;
- args[i]->print(&str, QT_ORDINARY);
+ args[i]->print(&str, QT_NO_DATA_EXPANSION);
str.append('\0');
my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "non geometric",
str.ptr());
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index b1d59c6170a..76ae66b9cfe 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -814,9 +814,10 @@ String *Item_func_des_encrypt::val_str(String *str)
/* We make good 24-byte (168 bit) key from given plaintext key with MD5 */
bzero((char*) &ivec,sizeof(ivec));
- EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL,
+ if (!EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL,
(uchar*) keystr->ptr(), (int) keystr->length(),
- 1, (uchar*) &keyblock,ivec);
+ 1, (uchar*) &keyblock,ivec))
+ goto error;
DES_set_key_unchecked(&keyblock.key1,&keyschedule.ks1);
DES_set_key_unchecked(&keyblock.key2,&keyschedule.ks2);
DES_set_key_unchecked(&keyblock.key3,&keyschedule.ks3);
@@ -909,9 +910,10 @@ String *Item_func_des_decrypt::val_str(String *str)
goto error;
bzero((char*) &ivec,sizeof(ivec));
- EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL,
+ if (!EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL,
(uchar*) keystr->ptr(),(int) keystr->length(),
- 1,(uchar*) &keyblock,ivec);
+ 1,(uchar*) &keyblock,ivec))
+ goto error;
// Here we set all 64-bit keys (56 effective) one by one
DES_set_key_unchecked(&keyblock.key1,&keyschedule.ks1);
DES_set_key_unchecked(&keyblock.key2,&keyschedule.ks2);
@@ -3568,7 +3570,7 @@ void Item_func_weight_string::fix_length_and_dec()
{
uint char_length;
char_length= ((cs->state & MY_CS_STRNXFRM_BAD_NWEIGHTS) || !nweights) ?
- args[0]->max_char_length() : nweights;
+ args[0]->max_char_length() : nweights * cs->levels_for_order;
max_length= cs->coll->strnxfrmlen(cs, char_length * cs->mbmaxlen);
}
maybe_null= 1;
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 28d33ac4f7c..8bb12ce0ac8 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -86,7 +86,6 @@ void Item_subselect::init(st_select_lex *select_lex,
DBUG_PRINT("enter", ("select_lex: 0x%lx this: 0x%lx",
(ulong) select_lex, (ulong) this));
unit= select_lex->master_unit();
- thd= unit->thd;
if (unit->item)
{
@@ -105,7 +104,7 @@ void Item_subselect::init(st_select_lex *select_lex,
Item can be changed in JOIN::prepare while engine in JOIN::optimize
=> we do not copy old_engine here
*/
- thd->change_item_tree((Item**)&unit->item, this);
+ unit->thd->change_item_tree((Item**)&unit->item, this);
engine->change_result(this, result, TRUE);
}
}
@@ -120,9 +119,9 @@ void Item_subselect::init(st_select_lex *select_lex,
NO_MATTER :
outer_select->parsing_place);
if (unit->is_union())
- engine= new subselect_union_engine(thd, unit, result, this);
+ engine= new subselect_union_engine(unit, result, this);
else
- engine= new subselect_single_select_engine(thd, select_lex, result, this);
+ engine= new subselect_single_select_engine(select_lex, result, this);
}
{
SELECT_LEX *upper= unit->outer_select();
@@ -239,6 +238,10 @@ bool Item_subselect::fix_fields(THD *thd_param, Item **ref)
uint8 uncacheable;
bool res;
+ thd= thd_param;
+
+ DBUG_ASSERT(unit->thd == thd);
+
status_var_increment(thd_param->status_var.feature_subquery);
DBUG_ASSERT(fixed == 0);
@@ -261,7 +264,7 @@ bool Item_subselect::fix_fields(THD *thd_param, Item **ref)
return TRUE;
- if (!(res= engine->prepare()))
+ if (!(res= engine->prepare(thd)))
{
// all transformation is done (used by prepared statements)
changed= 1;
@@ -565,22 +568,34 @@ bool Item_subselect::is_expensive()
for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select())
{
JOIN *cur_join= sl->join;
+
+ /* not optimized subquery */
if (!cur_join)
- continue;
+ return true;
+
+ /* very simple subquery */
+ if (!cur_join->tables_list && !sl->first_inner_unit())
+ return false;
+
+ /*
+ If the subquery is not optimised or in the process of optimization
+ it supposed to be expensive
+ */
+ if (!cur_join->optimized)
+ return true;
/*
Subqueries whose result is known after optimization are not expensive.
Such subqueries have all tables optimized away, thus have no join plan.
*/
- if (cur_join->optimized &&
- (cur_join->zero_result_cause || !cur_join->tables_list))
+ if ((cur_join->zero_result_cause || !cur_join->tables_list))
return false;
/*
If a subquery is not optimized we cannot estimate its cost. A subquery is
considered optimized if it has a join plan.
*/
- if (!(cur_join->optimized && cur_join->join_tab))
+ if (!cur_join->join_tab)
return true;
if (sl->first_inner_unit())
@@ -3163,9 +3178,12 @@ bool Item_in_subselect::fix_fields(THD *thd_arg, Item **ref)
{
uint outer_cols_num;
List<Item> *inner_cols;
- char const *save_where= thd->where;
+ char const *save_where= thd_arg->where;
DBUG_ENTER("Item_in_subselect::fix_fields");
+ thd= thd_arg;
+ DBUG_ASSERT(unit->thd == thd);
+
if (test_strategy(SUBS_SEMI_JOIN))
DBUG_RETURN( !( (*ref)= new (thd->mem_root) Item_int(thd, 1)) );
@@ -3282,7 +3300,8 @@ bool Item_in_subselect::setup_mat_engine()
if (!(mat_engine= new subselect_hash_sj_engine(thd, this, select_engine)))
DBUG_RETURN(TRUE);
- if (mat_engine->init(&select_engine->join->fields_list,
+ if (mat_engine->prepare(thd) ||
+ mat_engine->init(&select_engine->join->fields_list,
engine->get_identifier()))
DBUG_RETURN(TRUE);
@@ -3399,10 +3418,10 @@ void subselect_engine::set_thd(THD *thd_arg)
subselect_single_select_engine::
-subselect_single_select_engine(THD *thd_arg, st_select_lex *select,
+subselect_single_select_engine(st_select_lex *select,
select_result_interceptor *result_arg,
Item_subselect *item_arg)
- :subselect_engine(thd_arg, item_arg, result_arg),
+ :subselect_engine(item_arg, result_arg),
prepared(0), executed(0),
select_lex(select), join(0)
{
@@ -3483,10 +3502,10 @@ void subselect_uniquesubquery_engine::cleanup()
}
-subselect_union_engine::subselect_union_engine(THD *thd_arg, st_select_lex_unit *u,
+subselect_union_engine::subselect_union_engine(st_select_lex_unit *u,
select_result_interceptor *result_arg,
Item_subselect *item_arg)
- :subselect_engine(thd_arg, item_arg, result_arg)
+ :subselect_engine(item_arg, result_arg)
{
unit= u;
unit->item= item_arg;
@@ -3519,10 +3538,11 @@ subselect_union_engine::subselect_union_engine(THD *thd_arg, st_select_lex_unit
@retval 1 if error
*/
-int subselect_single_select_engine::prepare()
+int subselect_single_select_engine::prepare(THD *thd)
{
if (prepared)
return 0;
+ set_thd(thd);
if (select_lex->join)
{
select_lex->cleanup();
@@ -3550,12 +3570,13 @@ int subselect_single_select_engine::prepare()
return 0;
}
-int subselect_union_engine::prepare()
+int subselect_union_engine::prepare(THD *thd_arg)
{
+ set_thd(thd_arg);
return unit->prepare(thd, result, SELECT_NO_UNLOCK);
}
-int subselect_uniquesubquery_engine::prepare()
+int subselect_uniquesubquery_engine::prepare(THD *)
{
/* Should never be called. */
DBUG_ASSERT(FALSE);
@@ -5012,13 +5033,14 @@ subselect_hash_sj_engine::~subselect_hash_sj_engine()
}
-int subselect_hash_sj_engine::prepare()
+int subselect_hash_sj_engine::prepare(THD *thd_arg)
{
/*
Create and optimize the JOIN that will be used to materialize
the subquery if not yet created.
*/
- return materialize_engine->prepare();
+ set_thd(thd_arg);
+ return materialize_engine->prepare(thd);
}
@@ -5393,7 +5415,7 @@ int subselect_hash_sj_engine::exec()
if (strategy == PARTIAL_MATCH_MERGE)
{
pm_engine=
- new subselect_rowid_merge_engine(thd, (subselect_uniquesubquery_engine*)
+ new subselect_rowid_merge_engine((subselect_uniquesubquery_engine*)
lookup_engine, tmp_table,
count_pm_keys,
has_covering_null_row,
@@ -5402,6 +5424,7 @@ int subselect_hash_sj_engine::exec()
item, result,
semi_join_conds->argument_list());
if (!pm_engine ||
+ pm_engine->prepare(thd) ||
((subselect_rowid_merge_engine*) pm_engine)->
init(nn_key_parts, &partial_match_key_parts))
{
@@ -5419,13 +5442,14 @@ int subselect_hash_sj_engine::exec()
if (strategy == PARTIAL_MATCH_SCAN)
{
if (!(pm_engine=
- new subselect_table_scan_engine(thd, (subselect_uniquesubquery_engine*)
+ new subselect_table_scan_engine((subselect_uniquesubquery_engine*)
lookup_engine, tmp_table,
item, result,
semi_join_conds->argument_list(),
has_covering_null_row,
has_covering_null_columns,
- count_columns_with_nulls)))
+ count_columns_with_nulls)) ||
+ pm_engine->prepare(thd))
{
/* This is an irrecoverable error. */
res= 1;
@@ -5874,14 +5898,14 @@ void Ordered_key::print(String *str)
subselect_partial_match_engine::subselect_partial_match_engine(
- THD *thd_arg, subselect_uniquesubquery_engine *engine_arg,
+ subselect_uniquesubquery_engine *engine_arg,
TABLE *tmp_table_arg, Item_subselect *item_arg,
select_result_interceptor *result_arg,
List<Item> *equi_join_conds_arg,
bool has_covering_null_row_arg,
bool has_covering_null_columns_arg,
uint count_columns_with_nulls_arg)
- :subselect_engine(thd_arg, item_arg, result_arg),
+ :subselect_engine(item_arg, result_arg),
tmp_table(tmp_table_arg), lookup_engine(engine_arg),
equi_join_conds(equi_join_conds_arg),
has_covering_null_row(has_covering_null_row_arg),
@@ -6494,7 +6518,7 @@ end:
subselect_table_scan_engine::subselect_table_scan_engine(
- THD *thd_arg, subselect_uniquesubquery_engine *engine_arg,
+ subselect_uniquesubquery_engine *engine_arg,
TABLE *tmp_table_arg,
Item_subselect *item_arg,
select_result_interceptor *result_arg,
@@ -6502,7 +6526,7 @@ subselect_table_scan_engine::subselect_table_scan_engine(
bool has_covering_null_row_arg,
bool has_covering_null_columns_arg,
uint count_columns_with_nulls_arg)
- :subselect_partial_match_engine(thd_arg, engine_arg, tmp_table_arg, item_arg,
+ :subselect_partial_match_engine(engine_arg, tmp_table_arg, item_arg,
result_arg, equi_join_conds_arg,
has_covering_null_row_arg,
has_covering_null_columns_arg,
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index bec04813bcf..c39735384ed 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -754,7 +754,7 @@ public:
INDEXSUBQUERY_ENGINE, HASH_SJ_ENGINE,
ROWID_MERGE_ENGINE, TABLE_SCAN_ENGINE};
- subselect_engine(THD *thd_arg, Item_subselect *si,
+ subselect_engine(Item_subselect *si,
select_result_interceptor *res)
{
result= res;
@@ -762,7 +762,6 @@ public:
cmp_type= res_type= STRING_RESULT;
res_field_type= MYSQL_TYPE_VAR_STRING;
maybe_null= 0;
- set_thd(thd_arg);
}
virtual ~subselect_engine() {}; // to satisfy compiler
virtual void cleanup()= 0;
@@ -773,7 +772,7 @@ public:
*/
void set_thd(THD *thd_arg);
THD * get_thd() { return thd; }
- virtual int prepare()= 0;
+ virtual int prepare(THD *)= 0;
virtual void fix_length_and_dec(Item_cache** row)= 0;
/*
Execute the engine
@@ -828,11 +827,11 @@ class subselect_single_select_engine: public subselect_engine
st_select_lex *select_lex; /* corresponding select_lex */
JOIN * join; /* corresponding JOIN structure */
public:
- subselect_single_select_engine(THD *thd_arg, st_select_lex *select,
+ subselect_single_select_engine(st_select_lex *select,
select_result_interceptor *result,
Item_subselect *item);
void cleanup();
- int prepare();
+ int prepare(THD *thd);
void fix_length_and_dec(Item_cache** row);
int exec();
uint cols();
@@ -862,11 +861,11 @@ class subselect_union_engine: public subselect_engine
{
st_select_lex_unit *unit; /* corresponding unit structure */
public:
- subselect_union_engine(THD *thd_arg, st_select_lex_unit *u,
+ subselect_union_engine(st_select_lex_unit *u,
select_result_interceptor *result,
Item_subselect *item);
void cleanup();
- int prepare();
+ int prepare(THD *);
void fix_length_and_dec(Item_cache** row);
int exec();
uint cols();
@@ -919,11 +918,11 @@ public:
// constructor can assign THD because it will be called after JOIN::prepare
subselect_uniquesubquery_engine(THD *thd_arg, st_join_table *tab_arg,
Item_subselect *subs, Item *where)
- :subselect_engine(thd_arg, subs, 0), tab(tab_arg), cond(where)
+ :subselect_engine(subs, 0), tab(tab_arg), cond(where)
{}
~subselect_uniquesubquery_engine();
void cleanup();
- int prepare();
+ int prepare(THD *);
void fix_length_and_dec(Item_cache** row);
int exec();
uint cols() { return 1; }
@@ -1051,7 +1050,7 @@ public:
subselect_hash_sj_engine(THD *thd_arg, Item_subselect *in_predicate,
subselect_single_select_engine *old_engine)
- : subselect_engine(thd_arg, in_predicate, NULL),
+ : subselect_engine(in_predicate, NULL),
tmp_table(NULL), is_materialized(FALSE), materialize_engine(old_engine),
materialize_join(NULL), semi_join_conds(NULL), lookup_engine(NULL),
count_partial_match_columns(0), count_null_only_columns(0),
@@ -1061,7 +1060,7 @@ public:
bool init(List<Item> *tmp_columns, uint subquery_id);
void cleanup();
- int prepare();
+ int prepare(THD *);
int exec();
virtual void print(String *str, enum_query_type query_type);
uint cols()
@@ -1340,15 +1339,14 @@ protected:
protected:
virtual bool partial_match()= 0;
public:
- subselect_partial_match_engine(THD *thd_arg,
- subselect_uniquesubquery_engine *engine_arg,
+ subselect_partial_match_engine(subselect_uniquesubquery_engine *engine_arg,
TABLE *tmp_table_arg, Item_subselect *item_arg,
select_result_interceptor *result_arg,
List<Item> *equi_join_conds_arg,
bool has_covering_null_row_arg,
bool has_covering_null_columns_arg,
uint count_columns_with_nulls_arg);
- int prepare() { return 0; }
+ int prepare(THD *thd_arg) { set_thd(thd_arg); return 0; }
int exec();
void fix_length_and_dec(Item_cache**) {}
uint cols() { /* TODO: what is the correct value? */ return 1; }
@@ -1435,8 +1433,7 @@ protected:
bool exists_complementing_null_row(MY_BITMAP *keys_to_complement);
bool partial_match();
public:
- subselect_rowid_merge_engine(THD *thd_arg,
- subselect_uniquesubquery_engine *engine_arg,
+ subselect_rowid_merge_engine(subselect_uniquesubquery_engine *engine_arg,
TABLE *tmp_table_arg, uint merge_keys_count_arg,
bool has_covering_null_row_arg,
bool has_covering_null_columns_arg,
@@ -1444,7 +1441,7 @@ public:
Item_subselect *item_arg,
select_result_interceptor *result_arg,
List<Item> *equi_join_conds_arg)
- :subselect_partial_match_engine(thd_arg, engine_arg, tmp_table_arg,
+ :subselect_partial_match_engine(engine_arg, tmp_table_arg,
item_arg, result_arg, equi_join_conds_arg,
has_covering_null_row_arg,
has_covering_null_columns_arg,
@@ -1463,8 +1460,7 @@ class subselect_table_scan_engine: public subselect_partial_match_engine
protected:
bool partial_match();
public:
- subselect_table_scan_engine(THD *thd_arg,
- subselect_uniquesubquery_engine *engine_arg,
+ subselect_table_scan_engine(subselect_uniquesubquery_engine *engine_arg,
TABLE *tmp_table_arg, Item_subselect *item_arg,
select_result_interceptor *result_arg,
List<Item> *equi_join_conds_arg,
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 69eb3d63dd8..a4a694fe5eb 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -939,9 +939,8 @@ void Item_func_monthname::fix_length_and_dec()
{
THD* thd= current_thd;
CHARSET_INFO *cs= thd->variables.collation_connection;
- uint32 repertoire= my_charset_repertoire(cs);
locale= thd->variables.lc_time_names;
- collation.set(cs, DERIVATION_COERCIBLE, repertoire);
+ collation.set(cs, DERIVATION_COERCIBLE, locale->repertoire());
decimals=0;
max_length= locale->max_month_name_length * collation.collation->mbmaxlen;
maybe_null=1;
@@ -1086,9 +1085,8 @@ void Item_func_dayname::fix_length_and_dec()
{
THD* thd= current_thd;
CHARSET_INFO *cs= thd->variables.collation_connection;
- uint32 repertoire= my_charset_repertoire(cs);
locale= thd->variables.lc_time_names;
- collation.set(cs, DERIVATION_COERCIBLE, repertoire);
+ collation.set(cs, DERIVATION_COERCIBLE, locale->repertoire());
decimals=0;
max_length= locale->max_day_name_length * collation.collation->mbmaxlen;
maybe_null=1;
diff --git a/sql/lex.h b/sql/lex.h
index 0aaec5ffdda..d1762b2b20e 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -47,12 +47,9 @@ SYM_GROUP sym_group_rtree= {"RTree keys", "HAVE_RTREE_KEYS"};
static SYMBOL symbols[] = {
{ "&&", SYM(AND_AND_SYM)},
- { "<", SYM(LT)},
{ "<=", SYM(LE)},
{ "<>", SYM(NE)},
{ "!=", SYM(NE)},
- { "=", SYM(EQ)},
- { ">", SYM(GT_SYM)},
{ ">=", SYM(GE)},
{ "<<", SYM(SHIFT_LEFT)},
{ ">>", SYM(SHIFT_RIGHT)},
diff --git a/sql/log.cc b/sql/log.cc
index 39f001af554..fa8f10e5464 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
+/* Copyright (c) 2000, 2016, Oracle and/or its affiliates.
Copyright (c) 2009, 2016, MariaDB
This program is free software; you can redistribute it and/or modify
diff --git a/sql/log.h b/sql/log.h
index 40e9e4fdc58..a74a01f9c67 100644
--- a/sql/log.h
+++ b/sql/log.h
@@ -1,5 +1,5 @@
-/* Copyright (c) 2005, 2012, Oracle and/or its affiliates.
- Copyright (c) 2009, 2012, Monty Program Ab
+/* Copyright (c) 2005, 2016, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2016, Monty Program Ab
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
diff --git a/sql/log_event.cc b/sql/log_event.cc
index dfd84b99d49..b1cf6a9024a 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2000, 2015, Oracle and/or its affiliates.
+ Copyright (c) 2000, 2016, Oracle and/or its affiliates.
Copyright (c) 2009, 2016, MariaDB
This program is free software; you can redistribute it and/or modify
@@ -3743,10 +3743,25 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
if (time_zone_len)
copy_str_and_move(&time_zone_str, &start, time_zone_len);
- if (user.length > 0)
+ if (user.length)
+ {
copy_str_and_move((const char **)&(user.str), &start, user.length);
- if (host.length > 0)
+ }
+ else
+ {
+ user.str= (char *) start++;
+ user.str[0]= '\0';
+ }
+
+ if (host.length)
+ {
copy_str_and_move((const char **)&(host.str), &start, host.length);
+ }
+ else
+ {
+ host.str= (char *) start++;
+ host.str[0]= '\0';
+ }
/**
if time_zone_len or catalog_len are 0, then time_zone and catalog
@@ -9835,9 +9850,6 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
/*
When the open and locking succeeded, we check all tables to
ensure that they still have the correct type.
-
- We can use a down cast here since we know that every table added
- to the tables_to_lock is a RPL_TABLE_LIST.
*/
{
@@ -9856,10 +9868,37 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
NOTE: The base tables are added here are removed when
close_thread_tables is called.
*/
- RPL_TABLE_LIST *ptr= rgi->tables_to_lock;
- for (uint i= 0 ; ptr && (i < rgi->tables_to_lock_count);
- ptr= static_cast<RPL_TABLE_LIST*>(ptr->next_global), i++)
+ TABLE_LIST *table_list_ptr= rgi->tables_to_lock;
+ for (uint i=0 ; table_list_ptr && (i < rgi->tables_to_lock_count);
+ table_list_ptr= table_list_ptr->next_global, i++)
{
+ /*
+ Below if condition takes care of skipping base tables that
+ make up the MERGE table (which are added by open_tables()
+ call). They are added next to the merge table in the list.
+ For eg: If RPL_TABLE_LIST is t3->t1->t2 (where t1 and t2
+ are base tables for merge table 't3'), open_tables will modify
+ the list by adding t1 and t2 again immediately after t3 in the
+ list (*not at the end of the list*). New table_to_lock list will
+ look like t3->t1'->t2'->t1->t2 (where t1' and t2' are TABLE_LIST
+ objects added by open_tables() call). There is no flag(or logic) in
+ open_tables() that can skip adding these base tables to the list.
+ So the logic here should take care of skipping them.
+
+ tables_to_lock_count logic will take care of skipping base tables
+ that are added at the end of the list.
+ For eg: If RPL_TABLE_LIST is t1->t2->t3, open_tables will modify
+ the list into t1->t2->t3->t1'->t2'. t1' and t2' will be skipped
+ because tables_to_lock_count logic in this for loop.
+ */
+ if (table_list_ptr->parent_l)
+ continue;
+ /*
+ We can use a down cast here since we know that every table added
+ to the tables_to_lock is a RPL_TABLE_LIST (or child table which is
+ skipped above).
+ */
+ RPL_TABLE_LIST *ptr= static_cast<RPL_TABLE_LIST*>(table_list_ptr);
DBUG_ASSERT(ptr->m_tabledef_valid);
TABLE *conv_table;
if (!ptr->m_tabledef.compatible_with(thd, rgi, ptr->table, &conv_table))
@@ -9901,6 +9940,12 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
TABLE_LIST *ptr= rgi->tables_to_lock;
for (uint i=0 ; ptr && (i < rgi->tables_to_lock_count); ptr= ptr->next_global, i++)
{
+ /*
+ Please see comment in above 'for' loop to know the reason
+ for this if condition
+ */
+ if (ptr->parent_l)
+ continue;
rgi->m_table_map.set_table(ptr->table_id, ptr->table);
/*
Following is passing flag about triggers on the server. The problem was
diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc
index ff2f7b156d5..0502f20d2b1 100644
--- a/sql/log_event_old.cc
+++ b/sql/log_event_old.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007, 2013, Oracle and/or its affiliates.
+/* Copyright (c) 2007, 2016, Oracle and/or its affiliates.
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
@@ -120,16 +120,25 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, rpl_group_info *rgi)
/*
When the open and locking succeeded, we check all tables to
ensure that they still have the correct type.
-
- We can use a down cast here since we know that every table added
- to the tables_to_lock is a RPL_TABLE_LIST.
*/
{
- RPL_TABLE_LIST *ptr= rgi->tables_to_lock;
- for (uint i= 0 ; ptr&& (i< rgi->tables_to_lock_count);
- ptr= static_cast<RPL_TABLE_LIST*>(ptr->next_global), i++)
+ TABLE_LIST *table_list_ptr= rgi->tables_to_lock;
+ for (uint i=0 ; table_list_ptr&& (i< rgi->tables_to_lock_count);
+ table_list_ptr= table_list_ptr->next_global, i++)
{
+ /*
+ Please see comment in log_event.cc-Rows_log_event::do_apply_event()
+ function for the explanation of the below if condition
+ */
+ if (table_list_ptr->parent_l)
+ continue;
+ /*
+ We can use a down cast here since we know that every table added
+ to the tables_to_lock is a RPL_TABLE_LIST(or child table which is
+ skipped above).
+ */
+ RPL_TABLE_LIST *ptr=static_cast<RPL_TABLE_LIST*>(table_list_ptr);
DBUG_ASSERT(ptr->m_tabledef_valid);
TABLE *conv_table;
if (!ptr->m_tabledef.compatible_with(thd, rgi, ptr->table, &conv_table))
@@ -162,7 +171,15 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, rpl_group_info *rgi)
*/
TABLE_LIST *ptr= rgi->tables_to_lock;
for (uint i=0; ptr && (i < rgi->tables_to_lock_count); ptr= ptr->next_global, i++)
+ {
+ /*
+ Please see comment in log_event.cc-Rows_log_event::do_apply_event()
+ function for the explanation of the below if condition
+ */
+ if (ptr->parent_l)
+ continue;
rgi->m_table_map.set_table(ptr->table_id, ptr->table);
+ }
#ifdef HAVE_QUERY_CACHE
query_cache.invalidate_locked_for_write(thd, rgi->tables_to_lock);
#endif
@@ -1420,16 +1437,25 @@ int Old_rows_log_event::do_apply_event(rpl_group_info *rgi)
/*
When the open and locking succeeded, we check all tables to
ensure that they still have the correct type.
-
- We can use a down cast here since we know that every table added
- to the tables_to_lock is a RPL_TABLE_LIST.
*/
{
- RPL_TABLE_LIST *ptr= rgi->tables_to_lock;
- for (uint i= 0 ; ptr&& (i< rgi->tables_to_lock_count);
- ptr= static_cast<RPL_TABLE_LIST*>(ptr->next_global), i++)
+ TABLE_LIST *table_list_ptr= rgi->tables_to_lock;
+ for (uint i=0; table_list_ptr&& (i< rgi->tables_to_lock_count);
+ table_list_ptr= static_cast<RPL_TABLE_LIST*>(table_list_ptr->next_global), i++)
{
+ /*
+ Please see comment in log_event.cc-Rows_log_event::do_apply_event()
+ function for the explanation of the below if condition
+ */
+ if (table_list_ptr->parent_l)
+ continue;
+ /*
+ We can use a down cast here since we know that every table added
+ to the tables_to_lock is a RPL_TABLE_LIST (or child table which is
+ skipped above).
+ */
+ RPL_TABLE_LIST *ptr=static_cast<RPL_TABLE_LIST*>(table_list_ptr);
TABLE *conv_table;
if (ptr->m_tabledef.compatible_with(thd, rgi, ptr->table, &conv_table))
{
diff --git a/sql/mem_root_array.h b/sql/mem_root_array.h
index 2dcc475cd7b..5daeedadcba 100644
--- a/sql/mem_root_array.h
+++ b/sql/mem_root_array.h
@@ -47,12 +47,21 @@ template<typename Element_type, bool has_trivial_destructor>
class Mem_root_array
{
public:
+ /// Convenience typedef, same typedef name as std::vector
+ typedef Element_type value_type;
+
Mem_root_array(MEM_ROOT *root)
: m_root(root), m_array(NULL), m_size(0), m_capacity(0)
{
DBUG_ASSERT(m_root != NULL);
}
+ Mem_root_array(MEM_ROOT *root, size_t n, const value_type &val= value_type())
+ : m_root(root), m_array(NULL), m_size(0), m_capacity(0)
+ {
+ resize(n, val);
+ }
+
~Mem_root_array()
{
clear();
@@ -70,6 +79,12 @@ public:
return m_array[n];
}
+ Element_type &operator[](size_t n) { return at(n); }
+ const Element_type &operator[](size_t n) const { return at(n); }
+
+ Element_type &back() { return at(size() - 1); }
+ const Element_type &back() const { return at(size() - 1); }
+
// Returns a pointer to the first element in the array.
Element_type *begin() { return &m_array[0]; }
@@ -155,6 +170,58 @@ public:
return false;
}
+ /**
+ Removes the last element in the array, effectively reducing the
+ container size by one. This destroys the removed element.
+ */
+ void pop_back()
+ {
+ DBUG_ASSERT(!empty());
+ if (!has_trivial_destructor)
+ back().~Element_type();
+ m_size-= 1;
+ }
+
+ /**
+ Resizes the container so that it contains n elements.
+
+ If n is smaller than the current container size, the content is
+ reduced to its first n elements, removing those beyond (and
+ destroying them).
+
+ If n is greater than the current container size, the content is
+ expanded by inserting at the end as many elements as needed to
+ reach a size of n. If val is specified, the new elements are
+ initialized as copies of val, otherwise, they are
+ value-initialized.
+
+ If n is also greater than the current container capacity, an automatic
+ reallocation of the allocated storage space takes place.
+
+ Notice that this function changes the actual content of the
+ container by inserting or erasing elements from it.
+ */
+ void resize(size_t n, const value_type &val= value_type())
+ {
+ if (n == m_size)
+ return;
+ if (n > m_size)
+ {
+ if (!reserve(n))
+ {
+ while (n != m_size)
+ push_back(val);
+ }
+ return;
+ }
+ if (!has_trivial_destructor)
+ {
+ while (n != m_size)
+ pop_back();
+ }
+ m_size= n;
+ }
+
size_t capacity() const { return m_capacity; }
size_t element_size() const { return sizeof(Element_type); }
bool empty() const { return size() == 0; }
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 7173ee66959..fa8f143335d 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -290,7 +290,7 @@ const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"};
static const char *tc_heuristic_recover_names[]=
{
- "COMMIT", "ROLLBACK", NullS
+ "OFF", "COMMIT", "ROLLBACK", NullS
};
static TYPELIB tc_heuristic_recover_typelib=
{
@@ -4271,14 +4271,6 @@ static int init_common_variables()
else
opt_log_basename= glob_hostname;
-#ifdef WITH_WSREP
- if (wsrep_node_name == 0 || wsrep_node_name[0] == 0)
- {
- my_free((void *)wsrep_node_name);
- wsrep_node_name= my_strdup(glob_hostname, MYF(MY_WME));
- }
-#endif /* WITH_WSREP */
-
strmake(pidfile_name, opt_log_basename, sizeof(pidfile_name)-5);
strmov(fn_ext(pidfile_name),".pid"); // Add proper extension
SYSVAR_AUTOSIZE(pidfile_name_ptr, pidfile_name);
@@ -9214,6 +9206,7 @@ mysqld_get_one_option(int optid, const struct my_option *opt, char *argument)
log_error_file_ptr= const_cast<char*>("");
break;
case OPT_IGNORE_DB_DIRECTORY:
+ opt_ignore_db_dirs= NULL; // will be set in ignore_db_dirs_process_additions
if (*argument == 0)
ignore_db_dirs_reset();
else
@@ -9307,6 +9300,16 @@ mysqld_get_one_option(int optid, const struct my_option *opt, char *argument)
#endif
break;
}
+#ifdef WITH_WSREP
+ case OPT_WSREP_CAUSAL_READS:
+ wsrep_causal_reads_update(&global_system_variables);
+ break;
+ case OPT_WSREP_SYNC_WAIT:
+ global_system_variables.wsrep_causal_reads=
+ MY_TEST(global_system_variables.wsrep_sync_wait &
+ WSREP_SYNC_WAIT_BEFORE_READ);
+ break;
+#endif /* WITH_WSREP */
}
return 0;
}
diff --git a/sql/mysqld.h b/sql/mysqld.h
index a49778db012..6783eeff810 100644
--- a/sql/mysqld.h
+++ b/sql/mysqld.h
@@ -1,5 +1,5 @@
-/* Copyright (c) 2006, 2015, Oracle and/or its affiliates.
- Copyright (c) 2010, 2015, MariaDB
+/* Copyright (c) 2006, 2016, Oracle and/or its affiliates.
+ Copyright (c) 2010, 2016, 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
@@ -639,6 +639,10 @@ enum options_mysqld
OPT_SSL_KEY,
OPT_THREAD_CONCURRENCY,
OPT_WANT_CORE,
+#ifdef WITH_WSREP
+ OPT_WSREP_CAUSAL_READS,
+ OPT_WSREP_SYNC_WAIT,
+#endif /* WITH_WSREP */
OPT_MYSQL_COMPATIBILITY,
OPT_MYSQL_TO_BE_IMPLEMENTED,
OPT_which_is_always_the_last
@@ -686,7 +690,12 @@ enum enum_query_type
/// Be more detailed than QT_EXPLAIN.
/// Perhaps we should eventually include QT_ITEM_IDENT_SKIP_CURRENT_DATABASE
/// here, as it would give better readable results
- QT_EXPLAIN_EXTENDED= QT_TO_SYSTEM_CHARSET
+ QT_EXPLAIN_EXTENDED= QT_TO_SYSTEM_CHARSET,
+
+ // If an expression is constant, print the expression, not the value
+ // it evaluates to. Should be used for error messages, so that they
+ // don't reveal values.
+ QT_NO_DATA_EXPANSION= (1 << 9),
};
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 08c93d3a6ed..bd191f715e0 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -255,12 +255,19 @@ public:
(type == SEL_TREE::IMPOSSIBLE)
*/
enum Type { IMPOSSIBLE, ALWAYS, MAYBE, KEY, KEY_SMALLER } type;
- SEL_TREE(enum Type type_arg) :type(type_arg) {}
- SEL_TREE() :type(KEY)
+
+ SEL_TREE(enum Type type_arg, MEM_ROOT *root, size_t num_keys)
+ : type(type_arg), keys(root, num_keys), n_ror_scans(0)
{
keys_map.clear_all();
- bzero((char*) keys,sizeof(keys));
}
+
+ SEL_TREE(MEM_ROOT *root, size_t num_keys) :
+ type(KEY), keys(root, num_keys), n_ror_scans(0)
+ {
+ keys_map.clear_all();
+ }
+
SEL_TREE(SEL_TREE *arg, bool without_merges, RANGE_OPT_PARAM *param);
/*
Note: there may exist SEL_TREE objects with sel_tree->type=KEY and
@@ -268,7 +275,8 @@ public:
merit in range analyzer functions (e.g. get_mm_parts) returning a
pointer to such SEL_TREE instead of NULL)
*/
- SEL_ARG *keys[MAX_KEY];
+ Mem_root_array<SEL_ARG *, true> keys;
+
key_map keys_map; /* bitmask of non-NULL elements in keys */
/*
@@ -578,7 +586,7 @@ int SEL_IMERGE::and_sel_tree(RANGE_OPT_PARAM *param, SEL_TREE *tree,
{
SEL_TREE *res_or_tree= 0;
SEL_TREE *and_tree= 0;
- if (!(res_or_tree= new SEL_TREE()) ||
+ if (!(res_or_tree= new SEL_TREE(param->mem_root, param->keys)) ||
!(and_tree= new SEL_TREE(tree, TRUE, param)))
return (-1);
if (!and_range_trees(param, *or_tree, and_tree, res_or_tree))
@@ -787,7 +795,10 @@ int SEL_IMERGE::or_sel_imerge_with_checks(RANGE_OPT_PARAM *param,
*/
SEL_TREE::SEL_TREE(SEL_TREE *arg, bool without_merges,
- RANGE_OPT_PARAM *param): Sql_alloc()
+ RANGE_OPT_PARAM *param)
+ : Sql_alloc(),
+ keys(param->mem_root, param->keys),
+ n_ror_scans(0)
{
keys_map= arg->keys_map;
type= arg->type;
@@ -3022,9 +3033,7 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
PARAM param;
MEM_ROOT alloc;
SEL_TREE *tree;
- SEL_ARG **key, **end;
double rows;
- uint idx= 0;
init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0,
MYF(MY_THREAD_SPECIFIC));
@@ -3069,11 +3078,12 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
goto free_alloc;
}
- for (key= tree->keys, end= key + param.keys; key != end; key++, idx++)
+ for (uint idx= 0; idx < param.keys; idx++)
{
- if (*key)
+ SEL_ARG *key= tree->keys[idx];
+ if (key)
{
- if ((*key)->type == SEL_ARG::IMPOSSIBLE)
+ if (key->type == SEL_ARG::IMPOSSIBLE)
{
rows= 0;
table->reginfo.impossible_range= 1;
@@ -3081,10 +3091,10 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
}
else
{
- rows= records_in_column_ranges(&param, idx, *key);
+ rows= records_in_column_ranges(&param, idx, key);
if (rows != HA_POS_ERROR)
- (*key)->field->cond_selectivity= rows/table_records;
- }
+ key->field->cond_selectivity= rows/table_records;
+ }
}
}
@@ -4948,8 +4958,8 @@ TABLE_READ_PLAN *merge_same_index_scans(PARAM *param, SEL_IMERGE *imerge,
{
SEL_TREE **changed_tree= imerge->trees+(*tree_idx_ptr-1);
SEL_ARG *key= (*changed_tree)->keys[key_idx];
- bzero((*changed_tree)->keys,
- sizeof((*changed_tree)->keys[0])*param->keys);
+ for (uint i= 0; i < param->keys; i++)
+ (*changed_tree)->keys[i]= NULL;
(*changed_tree)->keys_map.clear_all();
if (key)
key->incr_refs();
@@ -6726,8 +6736,8 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
bool update_tbl_stats,
double read_time)
{
- uint idx;
- SEL_ARG **key,**end, **key_to_read= NULL;
+ uint idx, best_idx;
+ SEL_ARG *key_to_read= NULL;
ha_rows UNINIT_VAR(best_records); /* protected by key_to_read */
uint UNINIT_VAR(best_mrr_flags), /* protected by key_to_read */
UNINIT_VAR(best_buf_size); /* protected by key_to_read */
@@ -6750,9 +6760,10 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
sizeof(INDEX_SCAN_INFO *) * param->keys);
}
tree->index_scans_end= tree->index_scans;
- for (idx= 0,key=tree->keys, end=key+param->keys; key != end; key++,idx++)
+ for (idx= 0; idx < param->keys; idx++)
{
- if (*key)
+ SEL_ARG *key= tree->keys[idx];
+ if (key)
{
ha_rows found_records;
Cost_estimate cost;
@@ -6760,14 +6771,14 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
uint mrr_flags, buf_size;
INDEX_SCAN_INFO *index_scan;
uint keynr= param->real_keynr[idx];
- if ((*key)->type == SEL_ARG::MAYBE_KEY ||
- (*key)->maybe_flag)
+ if (key->type == SEL_ARG::MAYBE_KEY ||
+ key->maybe_flag)
param->needed_reg->set_bit(keynr);
bool read_index_only= index_read_must_be_used ? TRUE :
(bool) param->table->covering_keys.is_set(keynr);
- found_records= check_quick_select(param, idx, read_index_only, *key,
+ found_records= check_quick_select(param, idx, read_index_only, key,
update_tbl_stats, &mrr_flags,
&buf_size, &cost);
@@ -6781,7 +6792,7 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
index_scan->used_key_parts= param->max_key_part+1;
index_scan->range_count= param->range_count;
index_scan->records= found_records;
- index_scan->sel_arg= *key;
+ index_scan->sel_arg= key;
*tree->index_scans_end++= index_scan;
}
if ((found_records != HA_POS_ERROR) && param->is_ror_scan)
@@ -6795,6 +6806,7 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
read_time= found_read_time;
best_records= found_records;
key_to_read= key;
+ best_idx= idx;
best_mrr_flags= mrr_flags;
best_buf_size= buf_size;
}
@@ -6805,17 +6817,16 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
"ROR scans"););
if (key_to_read)
{
- idx= key_to_read - tree->keys;
- if ((read_plan= new (param->mem_root) TRP_RANGE(*key_to_read, idx,
+ if ((read_plan= new (param->mem_root) TRP_RANGE(key_to_read, best_idx,
best_mrr_flags)))
{
read_plan->records= best_records;
- read_plan->is_ror= tree->ror_scans_map.is_set(idx);
+ read_plan->is_ror= tree->ror_scans_map.is_set(best_idx);
read_plan->read_cost= read_time;
read_plan->mrr_buf_size= best_buf_size;
DBUG_PRINT("info",
("Returning range plan for key %s, cost %g, records %lu",
- param->table->key_info[param->real_keynr[idx]].name,
+ param->table->key_info[param->real_keynr[best_idx]].name,
read_plan->read_cost, (ulong) read_plan->records));
}
}
@@ -7104,7 +7115,7 @@ SEL_TREE *Item_func_in::get_func_mm_tree(RANGE_OPT_PARAM *param,
DBUG_RETURN(NULL);
}
SEL_TREE *tree2;
- for (; i < array->count; i++)
+ for (; i < array->used_count; i++)
{
if (array->compare_elems(i, i-1))
{
@@ -7443,9 +7454,11 @@ SEL_TREE *Item::get_mm_tree_for_const(RANGE_OPT_PARAM *param)
MEM_ROOT *tmp_root= param->mem_root;
param->thd->mem_root= param->old_root;
SEL_TREE *tree;
- tree= val_int() ? new(tmp_root) SEL_TREE(SEL_TREE::ALWAYS) :
- new(tmp_root) SEL_TREE(SEL_TREE::IMPOSSIBLE);
+
+ const SEL_TREE::Type type= val_int()? SEL_TREE::ALWAYS: SEL_TREE::IMPOSSIBLE;
param->thd->mem_root= tmp_root;
+
+ tree= new (tmp_root) SEL_TREE(type, tmp_root, param->keys);
DBUG_RETURN(tree);
}
@@ -7471,7 +7484,8 @@ SEL_TREE *Item::get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr)
if ((ref_tables & param->current_table) ||
(ref_tables & ~(param->prev_tables | param->read_tables)))
DBUG_RETURN(0);
- DBUG_RETURN(new SEL_TREE(SEL_TREE::MAYBE));
+ DBUG_RETURN(new (param->mem_root) SEL_TREE(SEL_TREE::MAYBE, param->mem_root,
+ param->keys));
}
@@ -7589,7 +7603,8 @@ Item_bool_func::get_mm_parts(RANGE_OPT_PARAM *param, Field *field,
if (field->eq(key_part->field))
{
SEL_ARG *sel_arg=0;
- if (!tree && !(tree=new (param->thd->mem_root) SEL_TREE()))
+ if (!tree && !(tree=new (param->thd->mem_root) SEL_TREE(param->mem_root,
+ param->keys)))
DBUG_RETURN(0); // OOM
if (!value || !(value_used_tables & ~param->read_tables))
{
@@ -8552,14 +8567,31 @@ tree_or(RANGE_OPT_PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2)
imerge[0]= new SEL_IMERGE(tree1->merges.head(), 0, param);
}
bool no_imerge_from_ranges= FALSE;
- if (!(result= new SEL_TREE()))
- DBUG_RETURN(result);
/* Build the range part of the tree for the formula (1) */
if (sel_trees_can_be_ored(param, tree1, tree2, &ored_keys))
{
bool must_be_ored= sel_trees_must_be_ored(param, tree1, tree2, ored_keys);
no_imerge_from_ranges= must_be_ored;
+
+ if (no_imerge_from_ranges && no_merges1 && no_merges2)
+ {
+ /*
+ Reuse tree1 as the result in simple cases. This reduces memory usage
+ for e.g. "key IN (c1, ..., cN)" which produces a lot of ranges.
+ */
+ result= tree1;
+ result->keys_map.clear_all();
+ }
+ else
+ {
+ if (!(result= new (param->mem_root) SEL_TREE(param->mem_root,
+ param->keys)))
+ {
+ DBUG_RETURN(result);
+ }
+ }
+
key_map::Iterator it(ored_keys);
int key_no;
while ((key_no= it++) != key_map::Iterator::BITMAP_END)
@@ -8576,7 +8608,13 @@ tree_or(RANGE_OPT_PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2)
}
result->type= tree1->type;
}
-
+ else
+ {
+ if (!result && !(result= new (param->mem_root) SEL_TREE(param->mem_root,
+ param->keys)))
+ DBUG_RETURN(result);
+ }
+
if (no_imerge_from_ranges && no_merges1 && no_merges2)
{
if (result->keys_map.is_clear_all())
@@ -14381,16 +14419,12 @@ void QUICK_GROUP_MIN_MAX_SELECT::add_keys_and_lengths(String *key_names,
static void print_sel_tree(PARAM *param, SEL_TREE *tree, key_map *tree_map,
const char *msg)
{
- SEL_ARG **key,**end;
- int idx;
char buff[1024];
DBUG_ENTER("print_sel_tree");
String tmp(buff,sizeof(buff),&my_charset_bin);
tmp.length(0);
- for (idx= 0,key=tree->keys, end=key+param->keys ;
- key != end ;
- key++,idx++)
+ for (uint idx= 0; idx < param->keys; idx++)
{
if (tree_map->is_set(idx))
{
diff --git a/sql/opt_range_mrr.cc b/sql/opt_range_mrr.cc
index bff96c7d4cb..729c491a6f1 100644
--- a/sql/opt_range_mrr.cc
+++ b/sql/opt_range_mrr.cc
@@ -266,12 +266,28 @@ walk_up_n_right:
range->end_key.flag= (cur->max_key_flag & NEAR_MAX ? HA_READ_BEFORE_KEY :
HA_READ_AFTER_KEY);
range->end_key.keypart_map= make_prev_keypart_map(cur->max_key_parts);
-
+
+ KEY *key_info;
+ if (seq->real_keyno== MAX_KEY)
+ key_info= NULL;
+ else
+ key_info= &seq->param->table->key_info[seq->real_keyno];
+
+ /*
+ Conditions below:
+ (1) - range analysis is used for estimating condition selectivity
+ (2) - This is a unique key, and we have conditions for all its
+ user-defined key parts.
+ (3) - The table uses extended keys, and we have conditions for
+ all key parts.
+ */
if (!(cur->min_key_flag & ~NULL_RANGE) && !cur->max_key_flag &&
- (seq->real_keyno == MAX_KEY ||
- ((uint)key_tree->part+1 ==
- seq->param->table->key_info[seq->real_keyno].user_defined_key_parts &&
- (seq->param->table->key_info[seq->real_keyno].flags & HA_NOSAME))) &&
+ (!key_info || // (1)
+ ((uint)key_tree->part+1 == key_info->user_defined_key_parts && // (2)
+ key_info->flags & HA_NOSAME) || // (2)
+ (seq->param->table->s->use_ext_keys && // (3)
+ (uint)key_tree->part+1 == key_info->ext_key_parts) // (3)
+ ) &&
range->start_key.length == range->end_key.length &&
!memcmp(seq->param->min_key,seq->param->max_key,range->start_key.length))
range->range_flag= UNIQUE_RANGE | (cur->min_key_flag & NULL_RANGE);
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 55c6c075f48..a835c5824ff 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -2247,7 +2247,8 @@ bool optimize_semijoin_nests(JOIN *join, table_map all_table_map)
rows *= join->map2table[tableno]->table->quick_condition_rows;
sjm->rows= MY_MIN(sjm->rows, rows);
}
- memcpy(sjm->positions, join->best_positions + join->const_tables,
+ memcpy((uchar*) sjm->positions,
+ (uchar*) (join->best_positions + join->const_tables),
sizeof(POSITION) * n_tables);
/*
@@ -3349,7 +3350,7 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
SJ_MATERIALIZATION_INFO *sjm= s->emb_sj_nest->sj_mat_info;
sjm->is_used= TRUE;
sjm->is_sj_scan= FALSE;
- memcpy(pos - sjm->tables + 1, sjm->positions,
+ memcpy((uchar*) (pos - sjm->tables + 1), (uchar*) sjm->positions,
sizeof(POSITION) * sjm->tables);
recalculate_prefix_record_count(join, tablenr - sjm->tables + 1,
tablenr);
@@ -3365,8 +3366,8 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
sjm->is_used= TRUE;
sjm->is_sj_scan= TRUE;
first= pos->sjmat_picker.sjm_scan_last_inner - sjm->tables + 1;
- memcpy(join->best_positions + first,
- sjm->positions, sizeof(POSITION) * sjm->tables);
+ memcpy((uchar*) (join->best_positions + first),
+ (uchar*) sjm->positions, sizeof(POSITION) * sjm->tables);
recalculate_prefix_record_count(join, first, first + sjm->tables);
join->best_positions[first].sj_strategy= SJ_OPT_MATERIALIZE_SCAN;
join->best_positions[first].n_sj_tables= sjm->tables;
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index fad639a5ec5..f440b9b3a3d 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -6138,7 +6138,7 @@ ER_SLAVE_HEARTBEAT_FAILURE
eng "Unexpected master's heartbeat data: %s"
ger "Unerwartete Daten vom Heartbeat des Masters: %s"
ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE
- eng "The requested value for the heartbeat period is either negative or exceeds the maximum allowed (%s seconds)."
+ eng "The requested value for the heartbeat period is either negative or exceeds the maximum allowed (%u seconds)."
ER_UNUSED_14
eng "You should never see it"
ER_CONFLICT_FN_PARSE_ERROR
@@ -6508,8 +6508,8 @@ ER_PARTITION_EXCHANGE_FOREIGN_KEY
swe "Tabellen att byta ut mot partition har foreign key referenser: '%-.64s'"
ER_NO_SUCH_KEY_VALUE
eng "Key value '%-.192s' was not found in table '%-.192s.%-.192s'"
-ER_RPL_INFO_DATA_TOO_LONG
- eng "Data for column '%s' too long"
+ER_VALUE_TOO_LONG
+ eng "Too long value for '%s'"
ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE
eng "Replication event checksum verification failed while reading from network."
ER_BINLOG_READ_EVENT_CHECKSUM_FAILURE
diff --git a/sql/slave.cc b/sql/slave.cc
index 27825c431d3..d83bafa5b3d 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -1,5 +1,5 @@
-/* Copyright (c) 2000, 2015, Oracle and/or its affiliates.
- Copyright (c) 2008, 2016, MariaDB Corporation
+/* Copyright (c) 2000, 2016, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2016, 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
@@ -1358,6 +1358,10 @@ bool is_network_error(uint errorno)
errorno == ER_NET_READ_INTERRUPTED ||
errorno == ER_SERVER_SHUTDOWN)
return TRUE;
+#ifdef WITH_WSREP
+ if (errorno == ER_UNKNOWN_COM_ERROR)
+ return TRUE;
+#endif
return FALSE;
}
@@ -4345,7 +4349,8 @@ int check_temp_dir(char* tmp_file)
mysql_mutex_lock(&LOCK_start_thread);
if (check_temp_dir_run)
{
- result= check_temp_dir_result;
+ if ((result= check_temp_dir_result))
+ my_message(result, tmp_file, MYF(0));
goto end;
}
check_temp_dir_run= 1;
@@ -4380,7 +4385,6 @@ int check_temp_dir(char* tmp_file)
mysql_file_delete(key_file_misc, tmp_file, MYF(0));
end:
- check_temp_dir_result= result;
mysql_mutex_unlock(&LOCK_start_thread);
DBUG_RETURN(result);
}
@@ -4660,11 +4664,14 @@ pthread_handler_t handle_slave_sql(void *arg)
if (check_temp_dir(rli->slave_patternload_file))
{
+ check_temp_dir_result= thd->get_stmt_da()->sql_errno();
rli->report(ERROR_LEVEL, thd->get_stmt_da()->sql_errno(), NULL,
"Unable to use slave's temporary directory %s - %s",
slave_load_tmpdir, thd->get_stmt_da()->message());
goto err;
}
+ else
+ check_temp_dir_result= 0;
/* Load the set of seen GTIDs, if we did not already. */
if (rpl_load_gtid_slave_state(thd))
diff --git a/sql/slave.h b/sql/slave.h
index ca89064d773..7f412c1091c 100644
--- a/sql/slave.h
+++ b/sql/slave.h
@@ -1,5 +1,5 @@
-/*
- Copyright (c) 2000, 2010, Oracle and/or its affiliates.
+/* Copyright (c) 2000, 2016, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2016, 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
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 06a2022d914..6b048cec68b 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -1,6 +1,6 @@
/*
- Copyright (c) 2002, 2013, Oracle and/or its affiliates.
- Copyright (c) 2011, 2013, Monty Program Ab
+ Copyright (c) 2002, 2016, Oracle and/or its affiliates.
+ Copyright (c) 2011, 2016, 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
@@ -514,8 +514,10 @@ sp_name::init_qname(THD *thd)
bool
check_routine_name(LEX_STRING *ident)
{
- if (!ident || !ident->str || !ident->str[0] ||
- ident->str[ident->length-1] == ' ')
+ DBUG_ASSERT(ident);
+ DBUG_ASSERT(ident->str);
+
+ if (!ident->str[0] || ident->str[ident->length-1] == ' ')
{
my_error(ER_SP_WRONG_NAME, MYF(0), ident->str);
return TRUE;
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index fde894c0cf6..37e6e769a89 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -1,5 +1,5 @@
-/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
- Copyright (c) 2009, 2014, SkySQL Ab.
+/* Copyright (c) 2000, 2016, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2016, 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
@@ -742,9 +742,8 @@ static ACL_USER *find_user_wild(const char *host, const char *user, const char *
static ACL_ROLE *find_acl_role(const char *user);
static ROLE_GRANT_PAIR *find_role_grant_pair(const LEX_STRING *u, const LEX_STRING *h, const LEX_STRING *r);
static ACL_USER_BASE *find_acl_user_base(const char *user, const char *host);
-static bool update_user_table(THD *thd, TABLE *table, const char *host,
- const char *user, const char *new_password,
- uint new_password_len);
+static bool update_user_table(THD *, TABLE *, const char *, const char *, const
+ char *, uint);
static bool acl_load(THD *thd, TABLE_LIST *tables);
static bool grant_load(THD *thd, TABLE_LIST *tables);
static inline void get_grantor(THD *thd, char* grantor);
@@ -897,7 +896,9 @@ static bool validate_password(LEX_USER *user)
{
if (user->pwtext.length || !user->pwhash.length)
{
- struct validation_data data= { &user->user, &user->pwtext };
+ struct validation_data data= { &user->user,
+ user->pwtext.str ? &user->pwtext :
+ const_cast<LEX_STRING *>(&empty_lex_str) };
if (plugin_foreach(NULL, do_validate,
MariaDB_PASSWORD_VALIDATION_PLUGIN, &data))
{
@@ -1203,7 +1204,6 @@ static bool acl_load(THD *thd, TABLE_LIST *tables)
grant_version++; /* Privileges updated */
init_sql_alloc(&acl_memroot, ACL_ALLOC_BLOCK_SIZE, 0, MYF(0));
- (void) my_init_dynamic_array(&acl_hosts,sizeof(ACL_HOST), 20, 50, MYF(0));
if ((table= tables[HOST_TABLE].table)) // "host" table may not exist (e.g. in MySQL 5.6.7+)
{
if (init_read_record(&read_record_info, thd, table, NULL, NULL,
@@ -1265,10 +1265,6 @@ static bool acl_load(THD *thd, TABLE_LIST *tables)
NULL, NULL, 1, 1, FALSE))
goto end;
table->use_all_columns();
- (void) my_init_dynamic_array(&acl_users,sizeof(ACL_USER), 50, 100, MYF(0));
- (void) my_hash_init2(&acl_roles,50, &my_charset_utf8_bin,
- 0, 0, 0, (my_hash_get_key) acl_role_get_key, 0,
- (void (*)(void *))free_acl_role, 0);
username_char_length= MY_MIN(table->field[1]->char_length(),
USERNAME_CHAR_LENGTH);
@@ -1527,7 +1523,6 @@ static bool acl_load(THD *thd, TABLE_LIST *tables)
NULL, NULL, 1, 1, FALSE))
goto end;
table->use_all_columns();
- (void) my_init_dynamic_array(&acl_dbs,sizeof(ACL_DB), 50, 100, MYF(0));
while (!(read_record_info.read_record(&read_record_info)))
{
ACL_DB db;
@@ -1589,8 +1584,6 @@ static bool acl_load(THD *thd, TABLE_LIST *tables)
end_read_record(&read_record_info);
freeze_size(&acl_dbs);
- (void) my_init_dynamic_array(&acl_proxy_users, sizeof(ACL_PROXY_USER),
- 50, 100, MYF(0));
if ((table= tables[PROXIES_PRIV_TABLE].table))
{
if (init_read_record(&read_record_info, thd, table,
@@ -1627,10 +1620,7 @@ static bool acl_load(THD *thd, TABLE_LIST *tables)
FALSE))
goto end;
table->use_all_columns();
- /* account for every role mapping */
- (void) my_hash_init2(&acl_roles_mappings, 50, system_charset_info, 0, 0, 0,
- (my_hash_get_key) acl_role_map_get_key, 0, 0, 0);
MEM_ROOT temp_root;
init_alloc_root(&temp_root, ACL_ALLOC_BLOCK_SIZE, 0, MYF(0));
while (!(read_record_info.read_record(&read_record_info)))
@@ -1669,6 +1659,7 @@ static bool acl_load(THD *thd, TABLE_LIST *tables)
return_val= FALSE;
end:
+ end_read_record(&read_record_info);
thd->variables.sql_mode= old_sql_mode;
DBUG_RETURN(return_val);
}
@@ -1685,12 +1676,12 @@ void acl_free(bool end)
delete_dynamic(&acl_proxy_users);
my_hash_free(&acl_check_hosts);
my_hash_free(&acl_roles_mappings);
- plugin_unlock(0, native_password_plugin);
- plugin_unlock(0, old_password_plugin);
if (!end)
acl_cache->clear(1); /* purecov: inspected */
else
{
+ plugin_unlock(0, native_password_plugin);
+ plugin_unlock(0, old_password_plugin);
delete acl_cache;
acl_cache=0;
}
@@ -1752,6 +1743,15 @@ bool acl_reload(THD *thd)
old_acl_roles_mappings= acl_roles_mappings;
old_acl_proxy_users= acl_proxy_users;
old_acl_dbs= acl_dbs;
+ my_init_dynamic_array(&acl_hosts, sizeof(ACL_HOST), 20, 50, MYF(0));
+ my_init_dynamic_array(&acl_users, sizeof(ACL_USER), 50, 100, MYF(0));
+ my_init_dynamic_array(&acl_dbs, sizeof(ACL_DB), 50, 100, MYF(0));
+ my_init_dynamic_array(&acl_proxy_users, sizeof(ACL_PROXY_USER), 50, 100, MYF(0));
+ my_hash_init2(&acl_roles,50, &my_charset_utf8_bin,
+ 0, 0, 0, (my_hash_get_key) acl_role_get_key, 0,
+ (void (*)(void *))free_acl_role, 0);
+ my_hash_init2(&acl_roles_mappings, 50, system_charset_info, 0, 0, 0,
+ (my_hash_get_key) acl_role_map_get_key, 0, 0, 0);
old_mem= acl_memroot;
delete_dynamic(&acl_wild_hosts);
my_hash_free(&acl_check_hosts);
@@ -2034,7 +2034,7 @@ static int check_user_can_set_role(const char *user, const char *host,
{
/* have to clear the privileges */
/* get the current user */
- acl_user= find_user_exact(host, user);
+ acl_user= find_user_wild(host, user, ip);
if (acl_user == NULL)
{
my_error(ER_INVALID_CURRENT_USER, MYF(0), rolename);
@@ -3459,7 +3459,7 @@ static int replace_user_table(THD *thd, TABLE *table, LEX_USER &combo,
}
if (!old_row_exists || combo.pwtext.length || combo.pwhash.length)
- if (validate_password(&combo))
+ if (!handle_as_role && validate_password(&combo))
goto end;
/* Update table columns with new privileges */
@@ -7378,8 +7378,7 @@ bool check_grant_db(THD *thd, const char *db)
len= (uint) (end - helping) + 1;
/*
- If a role is set, we need to check for privileges
- here aswell
+ If a role is set, we need to check for privileges here as well.
*/
if (sctx->priv_role[0])
{
@@ -7393,11 +7392,10 @@ bool check_grant_db(THD *thd, const char *db)
for (uint idx=0 ; idx < column_priv_hash.records ; idx++)
{
- GRANT_TABLE *grant_table= (GRANT_TABLE*)
- my_hash_element(&column_priv_hash,
- idx);
+ GRANT_TABLE *grant_table= (GRANT_TABLE*) my_hash_element(&column_priv_hash,
+ idx);
if (len < grant_table->key_length &&
- !memcmp(grant_table->hash_key,helping,len) &&
+ !memcmp(grant_table->hash_key, helping, len) &&
compare_hostname(&grant_table->host, sctx->host, sctx->ip))
{
error= FALSE; /* Found match. */
@@ -7405,7 +7403,7 @@ bool check_grant_db(THD *thd, const char *db)
}
if (sctx->priv_role[0] &&
len2 < grant_table->key_length &&
- !memcmp(grant_table->hash_key,helping2,len) &&
+ !memcmp(grant_table->hash_key, helping2, len2) &&
(!grant_table->host.hostname || !grant_table->host.hostname[0]))
{
error= FALSE; /* Found role match */
@@ -7641,7 +7639,8 @@ ulong get_column_grant(THD *thd, GRANT_INFO *grant,
if (!grant_column)
priv|= (grant->privilege | grant_table_role->privs);
else
- priv|= (grant->privilege | grant_table->privs | grant_column->rights);
+ priv|= (grant->privilege | grant_table_role->privs |
+ grant_column->rights);
}
}
mysql_rwlock_unlock(&LOCK_grant);
@@ -7813,23 +7812,71 @@ static bool print_grants_for_role(THD *thd, ACL_ROLE * role)
}
+/** checks privileges for SHOW GRANTS and SHOW CREATE USER
+
+ @note that in case of SHOW CREATE USER the parser guarantees
+ that a role can never happen here, so *rolename will never
+ be assigned to
+*/
+static bool check_show_access(THD *thd, LEX_USER *lex_user, char **username,
+ char **hostname, char **rolename)
+{
+ DBUG_ENTER("check_show_access");
+
+ if (lex_user->user.str == current_user.str)
+ {
+ *username= thd->security_ctx->priv_user;
+ *hostname= thd->security_ctx->priv_host;
+ }
+ else if (lex_user->user.str == current_role.str)
+ {
+ *rolename= thd->security_ctx->priv_role;
+ }
+ else if (lex_user->user.str == current_user_and_current_role.str)
+ {
+ *username= thd->security_ctx->priv_user;
+ *hostname= thd->security_ctx->priv_host;
+ *rolename= thd->security_ctx->priv_role;
+ }
+ else
+ {
+ Security_context *sctx= thd->security_ctx;
+ bool do_check_access;
+
+ lex_user= get_current_user(thd, lex_user);
+ if (!lex_user)
+ DBUG_RETURN(TRUE);
+
+ if (lex_user->is_role())
+ {
+ *rolename= lex_user->user.str;
+ do_check_access= strcmp(*rolename, sctx->priv_role);
+ }
+ else
+ {
+ *username= lex_user->user.str;
+ *hostname= lex_user->host.str;
+ do_check_access= strcmp(*username, sctx->priv_user) ||
+ strcmp(*hostname, sctx->priv_host);
+ }
+
+ if (do_check_access && check_access(thd, SELECT_ACL, "mysql", 0, 0, 1, 0))
+ DBUG_RETURN(TRUE);
+ }
+ DBUG_RETURN(FALSE);
+}
bool mysql_show_create_user(THD *thd, LEX_USER *lex_user)
{
- const char *username = safe_str(lex_user->user.str);
- const char *hostname = safe_str(lex_user->host.str);
+ char *username= NULL, *hostname= NULL;
char buff[1024]; //Show create user should not take more than 1024 bytes.
Protocol *protocol= thd->protocol;
bool error= false;
ACL_USER *acl_user;
DBUG_ENTER("mysql_show_create_user");
- // Check if the command specifies a username or not.
- if (lex_user->user.str == current_user.str)
- {
- username= thd->security_ctx->priv_user;
- hostname= thd->security_ctx->priv_host;
- }
+ if (check_show_access(thd, lex_user, &username, &hostname, NULL))
+ DBUG_RETURN(TRUE);
List<Item> field_list;
strxmov(buff, "CREATE USER for ", username, "@", hostname, NullS);
@@ -7918,9 +7965,7 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user)
ACL_ROLE *acl_role= NULL;
char buff[1024];
Protocol *protocol= thd->protocol;
- char *username= NULL;
- char *hostname= NULL;
- char *rolename= NULL;
+ char *username= NULL, *hostname= NULL, *rolename= NULL;
DBUG_ENTER("mysql_show_grants");
if (!initialized)
@@ -7929,44 +7974,8 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user)
DBUG_RETURN(TRUE);
}
- mysql_rwlock_rdlock(&LOCK_grant);
- mysql_mutex_lock(&acl_cache->lock);
-
- if (lex_user->user.str == current_user.str)
- {
- username= thd->security_ctx->priv_user;
- hostname= thd->security_ctx->priv_host;
- }
- else if (lex_user->user.str == current_role.str)
- {
- rolename= thd->security_ctx->priv_role;
- }
- else if (lex_user->user.str == current_user_and_current_role.str)
- {
- username= thd->security_ctx->priv_user;
- hostname= thd->security_ctx->priv_host;
- rolename= thd->security_ctx->priv_role;
- }
- else
- {
- lex_user= get_current_user(thd, lex_user, false);
- if (!lex_user)
- {
- mysql_mutex_unlock(&acl_cache->lock);
- mysql_rwlock_unlock(&LOCK_grant);
- DBUG_RETURN(TRUE);
- }
-
- if (lex_user->is_role())
- {
- rolename= lex_user->user.str;
- }
- else
- {
- username= lex_user->user.str;
- hostname= lex_user->host.str;
- }
- }
+ if (check_show_access(thd, lex_user, &username, &hostname, &rolename))
+ DBUG_RETURN(TRUE);
DBUG_ASSERT(rolename || username);
List<Item> field_list;
@@ -7978,14 +7987,11 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user)
mysql_show_grants_get_fields(thd, &field_list, buff);
if (protocol->send_result_set_metadata(&field_list,
- Protocol::SEND_NUM_ROWS |
- Protocol::SEND_EOF))
- {
- mysql_mutex_unlock(&acl_cache->lock);
- mysql_rwlock_unlock(&LOCK_grant);
-
+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
- }
+
+ mysql_rwlock_rdlock(&LOCK_grant);
+ mysql_mutex_lock(&acl_cache->lock);
if (username)
{
@@ -12342,6 +12348,9 @@ static bool acl_check_ssl(THD *thd, const ACL_USER *acl_user)
return 1;
}
}
+ if (!acl_user->x509_issuer && !acl_user->x509_subject)
+ return 0; // all done
+
/* Prepare certificate (if exists) */
if (!(cert= SSL_get_peer_certificate(ssl)))
return 1;
diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc
index e76e5d830c9..578b78d8f35 100644
--- a/sql/sql_admin.cc
+++ b/sql/sql_admin.cc
@@ -384,9 +384,13 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
To allow concurrent execution of read-only operations we acquire
weak metadata lock for them.
*/
- table->mdl_request.set_type((lock_type >= TL_WRITE_ALLOW_WRITE) ?
- MDL_SHARED_NO_READ_WRITE : MDL_SHARED_READ);
+ table->mdl_request.set_type(lex->sql_command == SQLCOM_REPAIR
+ ? MDL_SHARED_NO_READ_WRITE
+ : lock_type >= TL_WRITE_ALLOW_WRITE
+ ? MDL_SHARED_WRITE : MDL_SHARED_READ);
+
/* open only one table from local list of command */
+ while (1)
{
TABLE_LIST *save_next_global, *save_next_local;
save_next_global= table->next_global;
@@ -486,6 +490,20 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
result_code= HA_ADMIN_FAILED;
goto send_result;
}
+
+ if (!table->table || table->mdl_request.type != MDL_SHARED_WRITE ||
+ table->table->file->ha_table_flags() & HA_CONCURRENT_OPTIMIZE)
+ break;
+
+ trans_rollback_stmt(thd);
+ trans_rollback(thd);
+ close_thread_tables(thd);
+ table->table= NULL;
+ thd->mdl_context.release_transactional_locks();
+ table->mdl_request.init(MDL_key::TABLE, table->db, table->table_name,
+ MDL_SHARED_NO_READ_WRITE, MDL_TRANSACTION);
+ }
+
#ifdef WITH_PARTITION_STORAGE_ENGINE
if (table->table)
{
@@ -524,7 +542,6 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
}
}
#endif
- }
DBUG_PRINT("admin", ("table: 0x%lx", (long) table->table));
if (prepare_func)
@@ -625,18 +642,18 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
/*
Close all instances of the table to allow MyISAM "repair"
- to rename files.
+ (which is internally also used from "optimize") to rename files.
@todo: This code does not close all instances of the table.
It only closes instances in other connections, but if this
connection has LOCK TABLE t1 a READ, t1 b WRITE,
both t1 instances will be kept open.
- There is no need to execute this branch for InnoDB, which does
- repair by recreate. There is no need to do it for OPTIMIZE,
- which doesn't move files around.
- Hence, this code should be moved to prepare_for_repair(),
- and executed only for MyISAM engine.
+
+ Note that this code is only executed for engines that request
+ MDL_SHARED_NO_READ_WRITE lock (MDL_SHARED_WRITE cannot be upgraded)
+ by *not* having HA_CONCURRENT_OPTIMIZE table_flag.
*/
- if (lock_type == TL_WRITE && !table->table->s->tmp_table)
+ if (lock_type == TL_WRITE && !table->table->s->tmp_table &&
+ table->mdl_request.type > MDL_SHARED_WRITE)
{
if (wait_while_table_is_used(thd, table->table,
HA_EXTRA_PREPARE_FOR_RENAME))
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index f4af7dae207..3481bf1a2d3 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -7741,7 +7741,8 @@ fill_record(THD *thd, TABLE *table_arg, List<Item> &fields, List<Item> &values,
value=v++;
Field *rfield= field->field;
TABLE* table= rfield->table;
- if (rfield == table->next_number_field)
+ if (table->next_number_field &&
+ rfield->field_index == table->next_number_field->field_index)
table->auto_increment_field_not_null= TRUE;
if (rfield->vcol_info &&
value->type() != Item::DEFAULT_VALUE_ITEM &&
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 251f3eadfd8..9710ea8bbe3 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -2030,46 +2030,63 @@ bool THD::notify_shared_lock(MDL_context_owner *ctx_in_use,
{
THD *in_use= ctx_in_use->get_thd();
bool signalled= FALSE;
+ DBUG_ENTER("THD::notify_shared_lock");
+ DBUG_PRINT("enter",("needs_thr_lock_abort: %d", needs_thr_lock_abort));
if ((in_use->system_thread & SYSTEM_THREAD_DELAYED_INSERT) &&
!in_use->killed)
{
- in_use->killed= KILL_CONNECTION;
- mysql_mutex_lock(&in_use->mysys_var->mutex);
- if (in_use->mysys_var->current_cond)
- mysql_cond_broadcast(in_use->mysys_var->current_cond);
- mysql_mutex_unlock(&in_use->mysys_var->mutex);
+ /* This code is similar to kill_delayed_threads() */
+ DBUG_PRINT("info", ("kill delayed thread"));
+ mysql_mutex_lock(&in_use->LOCK_thd_data);
+ if (in_use->killed < KILL_CONNECTION)
+ in_use->killed= KILL_CONNECTION;
+ if (in_use->mysys_var)
+ {
+ mysql_mutex_lock(&in_use->mysys_var->mutex);
+ if (in_use->mysys_var->current_cond)
+ mysql_cond_broadcast(in_use->mysys_var->current_cond);
+
+ /* Abort if about to wait in thr_upgrade_write_delay_lock */
+ in_use->mysys_var->abort= 1;
+ mysql_mutex_unlock(&in_use->mysys_var->mutex);
+ }
+ mysql_mutex_unlock(&in_use->LOCK_thd_data);
signalled= TRUE;
}
if (needs_thr_lock_abort)
{
mysql_mutex_lock(&in_use->LOCK_thd_data);
- for (TABLE *thd_table= in_use->open_tables;
- thd_table ;
- thd_table= thd_table->next)
+ /* If not already dying */
+ if (in_use->killed != KILL_CONNECTION_HARD)
{
- /*
- Check for TABLE::needs_reopen() is needed since in some places we call
- handler::close() for table instance (and set TABLE::db_stat to 0)
- and do not remove such instances from the THD::open_tables
- for some time, during which other thread can see those instances
- (e.g. see partitioning code).
- */
- if (!thd_table->needs_reopen())
+ for (TABLE *thd_table= in_use->open_tables;
+ thd_table ;
+ thd_table= thd_table->next)
{
- signalled|= mysql_lock_abort_for_thread(this, thd_table);
- if (this && WSREP(this) && wsrep_thd_is_BF(this, FALSE))
+ /*
+ Check for TABLE::needs_reopen() is needed since in some
+ places we call handler::close() for table instance (and set
+ TABLE::db_stat to 0) and do not remove such instances from
+ the THD::open_tables for some time, during which other
+ thread can see those instances (e.g. see partitioning code).
+ */
+ if (!thd_table->needs_reopen())
{
- WSREP_DEBUG("remove_table_from_cache: %llu",
- (unsigned long long) this->real_id);
- wsrep_abort_thd((void *)this, (void *)in_use, FALSE);
+ signalled|= mysql_lock_abort_for_thread(this, thd_table);
+ if (this && WSREP(this) && wsrep_thd_is_BF(this, FALSE))
+ {
+ WSREP_DEBUG("remove_table_from_cache: %llu",
+ (unsigned long long) this->real_id);
+ wsrep_abort_thd((void *)this, (void *)in_use, FALSE);
+ }
}
}
}
mysql_mutex_unlock(&in_use->LOCK_thd_data);
}
- return signalled;
+ DBUG_RETURN(signalled);
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 0b952203a6c..0318b6a249c 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2000, 2015, Oracle and/or its affiliates.
+ Copyright (c) 2000, 2016, Oracle and/or its affiliates.
Copyright (c) 2009, 2016, MariaDB
This program is free software; you can redistribute it and/or modify
@@ -2280,6 +2280,18 @@ public:
current_stmt_binlog_format == BINLOG_FORMAT_ROW);
return current_stmt_binlog_format == BINLOG_FORMAT_ROW;
}
+ /**
+ Determine if binlogging is disabled for this session
+ @retval 0 if the current statement binlogging is disabled
+ (could be because of binlog closed/binlog option
+ is set to false).
+ @retval 1 if the current statement will be binlogged
+ */
+ inline bool is_current_stmt_binlog_disabled() const
+ {
+ return (!(variables.option_bits & OPTION_BIN_LOG) ||
+ !mysql_bin_log.is_open());
+ }
enum binlog_filter_state
{
diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc
index 7869f7f540c..fe6a101f999 100644
--- a/sql/sql_connect.cc
+++ b/sql/sql_connect.cc
@@ -1165,7 +1165,8 @@ void end_connection(THD *thd)
}
if (!thd->killed && (net->error && net->vio != 0))
- thd->print_aborted_warning(1, ER_THD(thd, ER_UNKNOWN_ERROR));
+ thd->print_aborted_warning(1, thd->get_stmt_da()->is_error()
+ ? thd->get_stmt_da()->message() : ER_THD(thd, ER_UNKNOWN_ERROR));
}
diff --git a/sql/sql_help.cc b/sql/sql_help.cc
index a50b90fc111..1ddddaf1b40 100644
--- a/sql/sql_help.cc
+++ b/sql/sql_help.cc
@@ -672,7 +672,7 @@ SQL_SELECT *prepare_select_for_name(THD *thd, const char *mask, uint mlen,
TRUE Error and send_error already commited
*/
-bool mysqld_help(THD *thd, const char *mask)
+static bool mysqld_help_internal(THD *thd, const char *mask)
{
Protocol *protocol= thd->protocol;
SQL_SELECT *select;
@@ -854,3 +854,12 @@ error2:
DBUG_RETURN(TRUE);
}
+
+bool mysqld_help(THD *thd, const char *mask)
+{
+ ulonglong sql_mode_backup= thd->variables.sql_mode;
+ thd->variables.sql_mode&= ~MODE_PAD_CHAR_TO_FULL_LENGTH;
+ bool rc= mysqld_help_internal(thd, mask);
+ thd->variables.sql_mode= sql_mode_backup;
+ return rc;
+}
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index fcfac2ed6af..d237360190e 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2000, 2015, Oracle and/or its affiliates.
+ Copyright (c) 2000, 2016, Oracle and/or its affiliates.
Copyright (c) 2010, 2016, MariaDB
This program is free software; you can redistribute it and/or modify
@@ -1607,9 +1607,10 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
else
table->file->insert_id_for_cur_row= insert_id_for_cur_row;
bool is_duplicate_key_error;
- if (table->file->is_fatal_error(error, HA_CHECK_DUP))
+ if (table->file->is_fatal_error(error, HA_CHECK_ALL))
goto err;
- is_duplicate_key_error= table->file->is_fatal_error(error, 0);
+ is_duplicate_key_error=
+ table->file->is_fatal_error(error, HA_CHECK_ALL & ~HA_CHECK_DUP);
if (!is_duplicate_key_error)
{
/*
@@ -1730,7 +1731,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
error != HA_ERR_RECORD_IS_THE_SAME)
{
if (info->ignore &&
- !table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
+ !table->file->is_fatal_error(error, HA_CHECK_ALL))
{
if (!(thd->variables.old_behavior &
OLD_MODE_NO_DUP_KEY_WARNINGS_WITH_IGNORE))
@@ -1860,7 +1861,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
{
DEBUG_SYNC(thd, "write_row_noreplace");
if (!info->ignore ||
- table->file->is_fatal_error(error, HA_CHECK_DUP))
+ table->file->is_fatal_error(error, HA_CHECK_ALL))
goto err;
if (!(thd->variables.old_behavior &
OLD_MODE_NO_DUP_KEY_WARNINGS_WITH_IGNORE))
@@ -1990,7 +1991,7 @@ public:
TABLE *table;
mysql_mutex_t mutex;
mysql_cond_t cond, cond_client;
- volatile uint tables_in_use,stacked_inserts;
+ uint tables_in_use, stacked_inserts;
volatile bool status;
bool retry;
/**
@@ -2676,14 +2677,16 @@ static void end_delayed_insert(THD *thd)
void kill_delayed_threads(void)
{
+ DBUG_ENTER("kill_delayed_threads");
mysql_mutex_lock(&LOCK_delayed_insert); // For unlink from list
I_List_iterator<Delayed_insert> it(delayed_threads);
Delayed_insert *di;
while ((di= it++))
{
- di->thd.killed= KILL_CONNECTION;
mysql_mutex_lock(&di->thd.LOCK_thd_data);
+ if (di->thd.killed < KILL_CONNECTION)
+ di->thd.killed= KILL_CONNECTION;
if (di->thd.mysys_var)
{
mysql_mutex_lock(&di->thd.mysys_var->mutex);
@@ -2704,6 +2707,7 @@ void kill_delayed_threads(void)
mysql_mutex_unlock(&di->thd.LOCK_thd_data);
}
mysql_mutex_unlock(&LOCK_delayed_insert); // For unlink from list
+ DBUG_VOID_RETURN;
}
@@ -2905,6 +2909,12 @@ pthread_handler_t handle_delayed_insert(void *arg)
/* Tell client that the thread is initialized */
mysql_cond_signal(&di->cond_client);
+ /*
+ Inform mdl that it needs to call mysql_lock_abort to abort locks
+ for delayed insert.
+ */
+ thd->mdl_context.set_needs_thr_lock_abort(TRUE);
+
di->table->mark_columns_needed_for_insert();
/* Now wait until we get an insert or lock to handle */
@@ -2915,6 +2925,7 @@ pthread_handler_t handle_delayed_insert(void *arg)
if (thd->killed)
{
uint lock_count;
+ DBUG_PRINT("delayed", ("Insert delayed killed"));
/*
Remove this from delay insert list so that no one can request a
table from this
@@ -2925,11 +2936,15 @@ pthread_handler_t handle_delayed_insert(void *arg)
lock_count=di->lock_count();
mysql_mutex_unlock(&LOCK_delayed_insert);
mysql_mutex_lock(&di->mutex);
- if (!lock_count && !di->tables_in_use && !di->stacked_inserts)
+ if (!lock_count && !di->tables_in_use && !di->stacked_inserts &&
+ !thd->lock)
break; // Time to die
}
/* Shouldn't wait if killed or an insert is waiting. */
+ DBUG_PRINT("delayed",
+ ("thd->killed: %d di->status: %d di->stacked_inserts: %d",
+ thd->killed, di->status, di->stacked_inserts));
if (!thd->killed && !di->status && !di->stacked_inserts)
{
struct timespec abstime;
@@ -2969,6 +2984,9 @@ pthread_handler_t handle_delayed_insert(void *arg)
mysql_mutex_unlock(&di->thd.mysys_var->mutex);
mysql_mutex_lock(&di->mutex);
}
+ DBUG_PRINT("delayed",
+ ("thd->killed: %d di->tables_in_use: %d thd->lock: %d",
+ thd->killed, di->tables_in_use, thd->lock != 0));
if (di->tables_in_use && ! thd->lock && !thd->killed)
{
@@ -3029,9 +3047,19 @@ pthread_handler_t handle_delayed_insert(void *arg)
{
DBUG_ENTER("handle_delayed_insert-cleanup");
di->table=0;
- thd->killed= KILL_CONNECTION; // If error
mysql_mutex_unlock(&di->mutex);
+ /*
+ Protect against mdl_locks trying to access open tables
+ We use KILL_CONNECTION_HARD here to ensure that
+ THD::notify_shared_lock() dosn't try to access open tables after
+ this.
+ */
+ mysql_mutex_lock(&thd->LOCK_thd_data);
+ thd->killed= KILL_CONNECTION_HARD; // If error
+ thd->mdl_context.set_needs_thr_lock_abort(0);
+ mysql_mutex_unlock(&thd->LOCK_thd_data);
+
close_thread_tables(thd); // Free the table
thd->mdl_context.release_transactional_locks();
mysql_cond_broadcast(&di->cond_client); // Safety
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index f83fd4cef3d..638f6832355 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1691,32 +1691,35 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd)
return (BIN_NUM);
case MY_LEX_CMP_OP: // Incomplete comparison operator
+ lip->next_state= MY_LEX_START; // Allow signed numbers
if (state_map[(uchar) lip->yyPeek()] == MY_LEX_CMP_OP ||
state_map[(uchar) lip->yyPeek()] == MY_LEX_LONG_CMP_OP)
- lip->yySkip();
- if ((tokval = find_keyword(lip, lip->yyLength() + 1, 0)))
{
- lip->next_state= MY_LEX_START; // Allow signed numbers
- return(tokval);
+ lip->yySkip();
+ if ((tokval= find_keyword(lip, 2, 0)))
+ return(tokval);
+ lip->yyUnget();
}
- state = MY_LEX_CHAR; // Something fishy found
- break;
+ return(c);
case MY_LEX_LONG_CMP_OP: // Incomplete comparison operator
+ lip->next_state= MY_LEX_START;
if (state_map[(uchar) lip->yyPeek()] == MY_LEX_CMP_OP ||
state_map[(uchar) lip->yyPeek()] == MY_LEX_LONG_CMP_OP)
{
lip->yySkip();
if (state_map[(uchar) lip->yyPeek()] == MY_LEX_CMP_OP)
+ {
lip->yySkip();
+ if ((tokval= find_keyword(lip, 3, 0)))
+ return(tokval);
+ lip->yyUnget();
+ }
+ if ((tokval= find_keyword(lip, 2, 0)))
+ return(tokval);
+ lip->yyUnget();
}
- if ((tokval = find_keyword(lip, lip->yyLength() + 1, 0)))
- {
- lip->next_state= MY_LEX_START; // Found long op
- return(tokval);
- }
- state = MY_LEX_CHAR; // Something fishy found
- break;
+ return(c);
case MY_LEX_BOOL:
if (c != lip->yyPeek())
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 951022e5085..b1167534491 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -1,6 +1,6 @@
/*
- Copyright (c) 2000, 2015, Oracle and/or its affiliates.
- Copyright (c) 2010, 2015, MariaDB
+ Copyright (c) 2000, 2016, Oracle and/or its affiliates.
+ Copyright (c) 2010, 2016, 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
@@ -348,6 +348,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
{
DBUG_RETURN(TRUE);
}
+ thd_proc_info(thd, "executing");
/*
Let us emit an error if we are loading data to table which is used
in subselect in SET clause like we do it for INSERT.
diff --git a/sql/sql_locale.cc b/sql/sql_locale.cc
index 5ac069de98b..58443a9a977 100644
--- a/sql/sql_locale.cc
+++ b/sql/sql_locale.cc
@@ -427,7 +427,7 @@ MY_LOCALE my_locale_da_DK
/***** LOCALE BEGIN de_AT: German - Austria *****/
static const char *my_locale_month_names_de_AT[13] =
- {"Jänner","Feber","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember", NullS };
+ {"Jänner","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember", NullS };
static const char *my_locale_ab_month_names_de_AT[13] =
{"Jän","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez", NullS };
static const char *my_locale_day_names_de_AT[8] =
diff --git a/sql/sql_locale.h b/sql/sql_locale.h
index e231393eec6..ec2f3d29e15 100644
--- a/sql/sql_locale.h
+++ b/sql/sql_locale.h
@@ -61,6 +61,8 @@ public:
grouping(grouping_par),
errmsgs(errmsgs_par)
{}
+ uint repertoire() const
+ { return is_ascii ? MY_REPERTOIRE_ASCII : MY_REPERTOIRE_EXTENDED; }
};
/* Exported variables */
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 63b44c53f94..5ff0bd98dba 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -5335,27 +5335,21 @@ end_with_restore_list:
#ifndef NO_EMBEDDED_ACCESS_CHECKS
case SQLCOM_SHOW_CREATE_USER:
- case SQLCOM_SHOW_GRANTS:
{
LEX_USER *grant_user= lex->grant_user;
- Security_context *sctx= thd->security_ctx;
if (!grant_user)
goto error;
- if (grant_user->user.str && !strcmp(sctx->priv_user, grant_user->user.str) &&
- grant_user->host.str && !strcmp(sctx->priv_host, grant_user->host.str))
- grant_user->user= current_user;
+ res = mysql_show_create_user(thd, grant_user);
+ break;
+ }
+ case SQLCOM_SHOW_GRANTS:
+ {
+ LEX_USER *grant_user= lex->grant_user;
+ if (!grant_user)
+ goto error;
- if (grant_user->user.str == current_user.str ||
- grant_user->user.str == current_role.str ||
- grant_user->user.str == current_user_and_current_role.str ||
- !check_access(thd, SELECT_ACL, "mysql", NULL, NULL, 1, 0))
- {
- if (lex->sql_command == SQLCOM_SHOW_GRANTS)
- res = mysql_show_grants(thd, grant_user);
- else
- res = mysql_show_create_user(thd, grant_user);
- }
+ res = mysql_show_grants(thd, grant_user);
break;
}
#endif
@@ -7063,6 +7057,7 @@ bool check_global_access(THD *thd, ulong want_access, bool no_errors)
temporary table flag)
@param alter_info [in] Initial list of columns and indexes for the
table to be created
+ @param create_db [in] Database of the created table
@retval
false ok.
@@ -7071,7 +7066,8 @@ bool check_global_access(THD *thd, ulong want_access, bool no_errors)
*/
bool check_fk_parent_table_access(THD *thd,
HA_CREATE_INFO *create_info,
- Alter_info *alter_info)
+ Alter_info *alter_info,
+ const char* create_db)
{
Key *key;
List_iterator<Key> key_iterator(alter_info->key_list);
@@ -7111,10 +7107,28 @@ bool check_fk_parent_table_access(THD *thd,
return true;
}
}
- else if (thd->lex->copy_db_to(&db_name.str, &db_name.length))
- return true;
else
- is_qualified_table_name= false;
+ {
+ if (!thd->db)
+ {
+ db_name.str= (char *) thd->memdup(create_db, strlen(create_db)+1);
+ db_name.length= strlen(create_db);
+ is_qualified_table_name= true;
+
+ if(create_db && check_db_name(&db_name))
+ {
+ my_error(ER_WRONG_DB_NAME, MYF(0), db_name.str);
+ return true;
+ }
+ }
+ else
+ {
+ if (thd->lex->copy_db_to(&db_name.str, &db_name.length))
+ return true;
+ else
+ is_qualified_table_name= false;
+ }
+ }
// if lower_case_table_names is set then convert tablename to lower case.
if (lower_case_table_names)
@@ -9327,7 +9341,7 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
goto err;
}
- if (check_fk_parent_table_access(thd, &lex->create_info, &lex->alter_info))
+ if (check_fk_parent_table_access(thd, &lex->create_info, &lex->alter_info, create_table->db))
goto err;
/*
diff --git a/sql/sql_parse.h b/sql/sql_parse.h
index aa8d0813870..ad29bb2cdd3 100644
--- a/sql/sql_parse.h
+++ b/sql/sql_parse.h
@@ -49,7 +49,8 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
TABLE_LIST *create_table);
bool check_fk_parent_table_access(THD *thd,
HA_CREATE_INFO *create_info,
- Alter_info *alter_info);
+ Alter_info *alter_info,
+ const char* create_db);
bool parse_sql(THD *thd, Parser_state *parser_state,
Object_creation_ctx *creation_ctx, bool do_pfs_digest=false);
diff --git a/sql/sql_plugin.h b/sql/sql_plugin.h
index 2bfdcb29dfc..efa48b22ce8 100644
--- a/sql/sql_plugin.h
+++ b/sql/sql_plugin.h
@@ -152,7 +152,7 @@ typedef int (*plugin_type_init)(struct st_plugin_int *);
extern I_List<i_string> *opt_plugin_load_list_ptr;
extern char *opt_plugin_dir_ptr;
-extern char opt_plugin_dir[FN_REFLEN];
+extern MYSQL_PLUGIN_IMPORT char opt_plugin_dir[FN_REFLEN];
extern const LEX_STRING plugin_type_names[];
extern ulong plugin_maturity;
extern TYPELIB plugin_maturity_values;
diff --git a/sql/sql_priv.h b/sql/sql_priv.h
index 5ac58f8cda7..40349d3802a 100644
--- a/sql/sql_priv.h
+++ b/sql/sql_priv.h
@@ -225,7 +225,7 @@
#define OPTIMIZER_SWITCH_TABLE_ELIMINATION (1ULL << 26)
#define OPTIMIZER_SWITCH_EXTENDED_KEYS (1ULL << 27)
#define OPTIMIZER_SWITCH_EXISTS_TO_IN (1ULL << 28)
-#define OPTIMIZER_SWITCH_USE_CONDITION_SELECTIVITY (1ULL << 29)
+#define OPTIMIZER_SWITCH_ORDERBY_EQ_PROP (1ULL << 29)
#define OPTIMIZER_SWITCH_DEFAULT (OPTIMIZER_SWITCH_INDEX_MERGE | \
OPTIMIZER_SWITCH_INDEX_MERGE_UNION | \
diff --git a/sql/sql_reload.cc b/sql/sql_reload.cc
index 25d4d93d75f..2fef615831b 100644
--- a/sql/sql_reload.cc
+++ b/sql/sql_reload.cc
@@ -1,4 +1,5 @@
-/* Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2010, 2016, Oracle and/or its affiliates.
+ Copyright (c) 2011, 2016, 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
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index bb68c44087b..cde2cc43b0f 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2015 Oracle and/or its affiliates.
+/* Copyright (c) 2000, 2016 Oracle and/or its affiliates.
Copyright (c) 2009, 2016 MariaDB
This program is free software; you can redistribute it and/or modify
@@ -12215,7 +12215,50 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond,
DBUG_PRINT("info",("removing: %s", order->item[0]->full_name()));
continue;
}
- *simple_order=0; // Must do a temp table to sort
+ /*
+ UseMultipleEqualitiesToRemoveTempTable:
+ Can use multiple-equalities here to check that ORDER BY columns
+ can be used without tmp. table.
+ */
+ bool can_subst_to_first_table= false;
+ if (optimizer_flag(join->thd, OPTIMIZER_SWITCH_ORDERBY_EQ_PROP) &&
+ first_is_base_table &&
+ order->item[0]->real_item()->type() == Item::FIELD_ITEM &&
+ join->cond_equal)
+ {
+ table_map first_table_bit=
+ join->join_tab[join->const_tables].table->map;
+
+ Item *item= order->item[0];
+
+ /*
+ TODO: equality substitution in the context of ORDER BY is
+ sometimes allowed when it is not allowed in the general case.
+
+ We make the below call for its side effect: it will locate the
+ multiple equality the item belongs to and set item->item_equal
+ accordingly.
+ */
+ Item *res= item->propagate_equal_fields(join->thd,
+ Value_source::
+ Context_identity(),
+ join->cond_equal);
+ Item_equal *item_eq;
+ if ((item_eq= res->get_item_equal()))
+ {
+ Item *first= item_eq->get_first(NO_PARTICULAR_TAB, NULL);
+ if (first->const_item() || first->used_tables() ==
+ first_table_bit)
+ {
+ can_subst_to_first_table= true;
+ }
+ }
+ }
+
+ if (!can_subst_to_first_table)
+ {
+ *simple_order=0; // Must do a temp table to sort
+ }
}
}
}
@@ -14315,6 +14358,8 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top,
if (table->outer_join && !table->embedding && table->table)
table->table->maybe_null= FALSE;
table->outer_join= 0;
+ if (!(straight_join || table->straight))
+ table->dep_tables= table->embedding? table->embedding->dep_tables: 0;
if (table->on_expr)
{
/* Add ON expression to the WHERE or upper-level ON condition. */
@@ -15725,7 +15770,7 @@ Field *Item::create_tmp_field(bool group, TABLE *table, uint convert_int_length)
new_field= tmp_table_field_from_field_type(table, true, false);
else
new_field= make_string_field(table);
- new_field->set_derivation(collation.derivation);
+ new_field->set_derivation(collation.derivation, collation.repertoire);
break;
case DECIMAL_RESULT:
new_field= Field_new_decimal::create_from_item(mem_root, this);
@@ -15992,7 +16037,8 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
modify_item);
case Item::TYPE_HOLDER:
result= ((Item_type_holder *)item)->make_field_by_type(table);
- result->set_derivation(item->collation.derivation);
+ result->set_derivation(item->collation.derivation,
+ item->collation.repertoire);
return result;
default: // Dosen't have to be stored
return 0;
@@ -20366,6 +20412,8 @@ part_of_refkey(TABLE *table,Field *field)
/**
Test if one can use the key to resolve ORDER BY.
+ @param join if not NULL, can use the join's top-level
+ multiple-equalities.
@param order Sort order
@param table Table to sort
@param idx Index to check
@@ -20388,7 +20436,8 @@ part_of_refkey(TABLE *table,Field *field)
-1 Reverse key can be used
*/
-static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
+static int test_if_order_by_key(JOIN *join,
+ ORDER *order, TABLE *table, uint idx,
uint *used_key_parts= NULL)
{
KEY_PART_INFO *key_part,*key_part_end;
@@ -20411,7 +20460,8 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
for (; order ; order=order->next, const_key_parts>>=1)
{
- Field *field=((Item_field*) (*order->item)->real_item())->field;
+ Item_field *item_field= ((Item_field*) (*order->item)->real_item());
+ Field *field= item_field->field;
int flag;
/*
@@ -20453,6 +20503,17 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
DBUG_RETURN(0);
}
+ if (key_part->field != field)
+ {
+ /*
+ Check if there is a multiple equality that allows to infer that field
+ and key_part->field are equal
+ (see also: compute_part_of_sort_key_for_equals)
+ */
+ if (item_field->item_equal &&
+ item_field->item_equal->contains(key_part->field))
+ field= key_part->field;
+ }
if (key_part->field != field || !field->part_of_sortkey.is_set(idx))
DBUG_RETURN(0);
@@ -20582,7 +20643,7 @@ test_if_subkey(ORDER *order, TABLE *table, uint ref, uint ref_key_parts,
table->key_info[nr].user_defined_key_parts >= ref_key_parts &&
is_subkey(table->key_info[nr].key_part, ref_key_part,
ref_key_part_end) &&
- test_if_order_by_key(order, table, nr))
+ test_if_order_by_key(NULL, order, table, nr))
{
min_length= table->key_info[nr].key_length;
best= nr;
@@ -20721,6 +20782,71 @@ find_field_in_item_list (Field *field, void *data)
}
+/*
+ Fill *col_keys with a union of Field::part_of_sortkey of all fields
+ that belong to 'table' and are equal to 'item_field'.
+*/
+
+void compute_part_of_sort_key_for_equals(JOIN *join, TABLE *table,
+ Item_field *item_field,
+ key_map *col_keys)
+{
+ col_keys->clear_all();
+ col_keys->merge(item_field->field->part_of_sortkey);
+
+ if (!optimizer_flag(join->thd, OPTIMIZER_SWITCH_ORDERBY_EQ_PROP))
+ return;
+
+ Item_equal *item_eq= NULL;
+
+ if (item_field->item_equal)
+ {
+ /*
+ The item_field is from ORDER structure, but it already has an item_equal
+ pointer set (UseMultipleEqualitiesToRemoveTempTable code have set it)
+ */
+ item_eq= item_field->item_equal;
+ }
+ else
+ {
+ /*
+ Walk through join's muliple equalities and find the one that contains
+ item_field.
+ */
+ if (!join->cond_equal)
+ return;
+ table_map needed_tbl_map= item_field->used_tables() | table->map;
+ List_iterator<Item_equal> li(join->cond_equal->current_level);
+ Item_equal *cur_item_eq;
+ while ((cur_item_eq= li++))
+ {
+ if ((cur_item_eq->used_tables() & needed_tbl_map) &&
+ cur_item_eq->contains(item_field->field))
+ {
+ item_eq= cur_item_eq;
+ item_field->item_equal= item_eq; // Save the pointer to our Item_equal.
+ break;
+ }
+ }
+ }
+
+ if (item_eq)
+ {
+ Item_equal_fields_iterator it(*item_eq);
+ Item *item;
+ /* Loop through other members that belong to table table */
+ while ((item= it++))
+ {
+ if (item->type() == Item::FIELD_ITEM &&
+ ((Item_field*)item)->field->table == table)
+ {
+ col_keys->merge(((Item_field*)item)->field->part_of_sortkey);
+ }
+ }
+ }
+}
+
+
/**
Test if we can skip the ORDER BY by using an index.
@@ -20777,7 +20903,27 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
usable_keys.clear_all();
DBUG_RETURN(0);
}
- usable_keys.intersect(((Item_field*) item)->field->part_of_sortkey);
+
+ /*
+ Take multiple-equalities into account. Suppose we have
+ ORDER BY col1, col10
+ and there are
+ multiple-equal(col1, col2, col3),
+ multiple-equal(col10, col11).
+
+ Then,
+ - when item=col1, we find the set of indexes that cover one of {col1,
+ col2, col3}
+ - when item=col10, we find the set of indexes that cover one of {col10,
+ col11}
+
+ And we compute an intersection of these sets to find set of indexes that
+ cover all ORDER BY components.
+ */
+ key_map col_keys;
+ compute_part_of_sort_key_for_equals(tab->join, table, (Item_field*)item,
+ &col_keys);
+ usable_keys.intersect(col_keys);
if (usable_keys.is_clear_all())
goto use_filesort; // No usable keys
}
@@ -20935,7 +21081,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
}
/* Check if we get the rows in requested sorted order by using the key */
if (usable_keys.is_set(ref_key) &&
- (order_direction= test_if_order_by_key(order,table,ref_key,
+ (order_direction= test_if_order_by_key(tab->join, order,table,ref_key,
&used_key_parts)))
goto check_reverse_order;
}
@@ -24594,33 +24740,53 @@ static void print_join(THD *thd,
/* List is reversed => we should reverse it before using */
List_iterator_fast<TABLE_LIST> ti(*tables);
TABLE_LIST **table;
- uint non_const_tables= 0;
DBUG_ENTER("print_join");
+ /*
+ If the QT_NO_DATA_EXPANSION flag is specified, we print the
+ original table list, including constant tables that have been
+ optimized away, as the constant tables may be referenced in the
+ expression printed by Item_field::print() when this flag is given.
+ Otherwise, only non-const tables are printed.
+
+ Example:
+
+ Original SQL:
+ select * from (select 1) t
+
+ Printed without QT_NO_DATA_EXPANSION:
+ select '1' AS `1` from dual
+
+ Printed with QT_NO_DATA_EXPANSION:
+ select `t`.`1` from (select 1 AS `1`) `t`
+ */
+ const bool print_const_tables= (query_type & QT_NO_DATA_EXPANSION);
+ size_t tables_to_print= 0;
+
for (TABLE_LIST *t= ti++; t ; t= ti++)
{
- /*
- See comment in print_table_array() about the second part of the
- condition
- */
- if (!t->optimized_away && !is_eliminated_table(eliminated_tables, t))
- non_const_tables++;
+ /* See comment in print_table_array() about the second condition */
+ if (print_const_tables || !t->optimized_away)
+ if (!is_eliminated_table(eliminated_tables, t))
+ tables_to_print++;
}
- if (!non_const_tables)
+ if (tables_to_print == 0)
{
str->append(STRING_WITH_LEN("dual"));
DBUG_VOID_RETURN; // all tables were optimized away
}
ti.rewind();
- if (!(table= (TABLE_LIST **)thd->alloc(sizeof(TABLE_LIST*) *
- non_const_tables)))
+ if (!(table= static_cast<TABLE_LIST **>(thd->alloc(sizeof(TABLE_LIST*) *
+ tables_to_print))))
DBUG_VOID_RETURN; // out of memory
- TABLE_LIST *tmp, **t= table + (non_const_tables - 1);
+ TABLE_LIST *tmp, **t= table + (tables_to_print - 1);
while ((tmp= ti++))
{
- if (tmp->optimized_away || is_eliminated_table(eliminated_tables, tmp))
+ if (tmp->optimized_away && !print_const_tables)
+ continue;
+ if (is_eliminated_table(eliminated_tables, tmp))
continue;
*t--= tmp;
}
@@ -24640,7 +24806,7 @@ static void print_join(THD *thd,
*/
if ((*table)->sj_inner_tables)
{
- TABLE_LIST **end= table + non_const_tables;
+ TABLE_LIST **end= table + tables_to_print;
for (TABLE_LIST **t2= table; t2!=end; t2++)
{
if (!(*t2)->sj_inner_tables)
@@ -24653,7 +24819,7 @@ static void print_join(THD *thd,
}
}
print_table_array(thd, eliminated_tables, str, table,
- table + non_const_tables, query_type);
+ table + tables_to_print, query_type);
DBUG_VOID_RETURN;
}
@@ -25076,7 +25242,7 @@ void JOIN::save_query_plan(Join_plan_state *save_to)
}
memcpy((uchar*) save_to->best_positions, (uchar*) best_positions,
sizeof(POSITION) * (table_count + 1));
- memset(best_positions, 0, sizeof(POSITION) * (table_count + 1));
+ memset((uchar*) best_positions, 0, sizeof(POSITION) * (table_count + 1));
/* Save SJM nests */
List_iterator<TABLE_LIST> it(select_lex->sj_nests);
@@ -25504,7 +25670,8 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table,
uint used_key_parts= 0;
if (keys.is_set(nr) &&
- (direction= test_if_order_by_key(order, table, nr, &used_key_parts)))
+ (direction= test_if_order_by_key(join, order, table, nr,
+ &used_key_parts)))
{
/*
At this point we are sure that ref_key is a non-ordering
@@ -25747,7 +25914,7 @@ uint get_index_for_order(ORDER *order, TABLE *table, SQL_SELECT *select,
}
uint used_key_parts;
- switch (test_if_order_by_key(order, table, select->quick->index,
+ switch (test_if_order_by_key(NULL, order, table, select->quick->index,
&used_key_parts)) {
case 1: // desired order
*need_sort= FALSE;
diff --git a/sql/sql_select.h b/sql/sql_select.h
index d4dc691c547..92ba74fac35 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -1939,8 +1939,6 @@ bool error_if_full_join(JOIN *join);
int report_error(TABLE *table, int error);
int safe_index_read(JOIN_TAB *tab);
int get_quick_record(SQL_SELECT *select);
-SORT_FIELD * make_unireg_sortorder(THD *thd, ORDER *order, uint *length,
- SORT_FIELD *sortorder);
int setup_order(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
List<Item> &fields, List <Item> &all_fields, ORDER *order,
bool search_in_all_fields= true);
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 5176bcbbc00..30c65e6e279 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -815,12 +815,24 @@ ignore_db_dirs_process_additions()
for (i= 0; i < ignore_db_dirs_array.elements; i++)
{
get_dynamic(&ignore_db_dirs_array, (uchar *) &dir, i);
- if (my_hash_insert(&ignore_db_dirs_hash, (uchar *) dir))
+ if (my_hash_insert(&ignore_db_dirs_hash, (uchar *)dir))
+ {
+ /* ignore duplicates from the config file */
+ if (my_hash_search(&ignore_db_dirs_hash, (uchar *)dir->str, dir->length))
+ {
+ sql_print_warning("Duplicate ignore-db-dir directory name '%.*s' "
+ "found in the config file(s). Ignoring the duplicate.",
+ (int) dir->length, dir->str);
+ my_free(dir);
+ goto continue_loop;
+ }
+
return true;
+ }
ptr= strnmov(ptr, dir->str, dir->length);
- if (i + 1 < ignore_db_dirs_array.elements)
- ptr= strmov(ptr, ",");
+ *(ptr++)= ',';
+continue_loop:
/*
Set the transferred array element to NULL to avoid double free
in case of error.
@@ -829,6 +841,12 @@ ignore_db_dirs_process_additions()
set_dynamic(&ignore_db_dirs_array, (uchar *) &dir, i);
}
+ if (ptr > opt_ignore_db_dirs)
+ {
+ ptr--;
+ DBUG_ASSERT(*ptr == ',');
+ }
+
/* make sure the string is terminated */
DBUG_ASSERT(ptr - opt_ignore_db_dirs <= (ptrdiff_t) len);
*ptr= 0;
diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc
index f6811b020eb..83c7db8b510 100644
--- a/sql/sql_statistics.cc
+++ b/sql/sql_statistics.cc
@@ -30,6 +30,7 @@
#include "opt_range.h"
#include "uniques.h"
#include "my_atomic.h"
+#include "sql_show.h"
/*
The system variable 'use_stat_tables' can take one of the
@@ -3195,6 +3196,10 @@ int delete_statistics_for_table(THD *thd, LEX_STRING *db, LEX_STRING *tab)
rc= 1;
}
+ err= del_global_table_stat(thd, db, tab);
+ if (err & !rc)
+ rc= 1;
+
thd->restore_stmt_binlog_format(save_binlog_format);
close_system_tables(thd, &open_tables_backup);
@@ -3341,6 +3346,10 @@ int delete_statistics_for_index(THD *thd, TABLE *tab, KEY *key_info,
}
}
+ err= del_global_index_stat(thd, tab, key_info);
+ if (err && !rc)
+ rc= 1;
+
thd->restore_stmt_binlog_format(save_binlog_format);
close_system_tables(thd, &open_tables_backup);
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 83aae3f5038..cb272402e90 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2000, 2015, Oracle and/or its affiliates.
+ Copyright (c) 2000, 2016, Oracle and/or its affiliates.
Copyright (c) 2010, 2016, MariaDB
This program is free software; you can redistribute it and/or modify
@@ -37,8 +37,7 @@
#include "sql_time.h" // make_truncated_value_warning
#include "records.h" // init_read_record, end_read_record
#include "filesort.h" // filesort_free_buffers
-#include "sql_select.h" // setup_order,
- // make_unireg_sortorder
+#include "sql_select.h" // setup_order
#include "sql_handler.h" // mysql_ha_rm_tables
#include "discover.h" // readfrm
#include "my_pthread.h" // pthread_mutex_t
@@ -5488,6 +5487,9 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
/*
We have to write the query before we unlock the tables.
*/
+ if (thd->is_current_stmt_binlog_disabled())
+ goto err;
+
if (thd->is_current_stmt_binlog_format_row())
{
/*
@@ -5558,6 +5560,21 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
*/
if (!table->view)
{
+ /*
+ After opening a MERGE table add the children to the query list of
+ tables, so that children tables info can be used on "CREATE TABLE"
+ statement generation by the binary log.
+ Note that placeholders don't have the handler open.
+ */
+ if (table->table->file->extra(HA_EXTRA_ADD_CHILDREN_LIST))
+ goto err;
+
+ /*
+ As the reference table is temporary and may not exist on slave, we must
+ force the ENGINE to be present into CREATE TABLE.
+ */
+ create_info->used_fields|= HA_CREATE_USED_ENGINE;
+
int result __attribute__((unused))=
show_create_table(thd, table, &query, create_info, WITH_DB_NAME);
@@ -8599,7 +8616,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
till this point for the alter operation.
*/
if ((alter_info->flags & Alter_info::ADD_FOREIGN_KEY) &&
- check_fk_parent_table_access(thd, create_info, alter_info))
+ check_fk_parent_table_access(thd, create_info, alter_info, new_db))
DBUG_RETURN(true);
/*
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 5c20b72930e..d59b8b7e048 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -1,5 +1,5 @@
-/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
- Copyright (c) 2011, 2015, MariaDB
+/* Copyright (c) 2000, 2016, Oracle and/or its affiliates.
+ Copyright (c) 2011, 2016, 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
@@ -818,7 +818,7 @@ int mysql_update(THD *thd,
error= 0;
}
else if (!ignore ||
- table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
+ table->file->is_fatal_error(error, HA_CHECK_ALL))
{
/*
If (ignore && error is ignorable) we don't have to
@@ -826,7 +826,7 @@ int mysql_update(THD *thd,
*/
myf flags= 0;
- if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
+ if (table->file->is_fatal_error(error, HA_CHECK_ALL))
flags|= ME_FATALERROR; /* Other handler errors are fatal */
prepare_record_for_error_message(error, table);
@@ -1593,7 +1593,7 @@ bool mysql_multi_update(THD *thd,
DBUG_RETURN(TRUE);
}
- thd->abort_on_warning= thd->is_strict_mode();
+ thd->abort_on_warning= !ignore && thd->is_strict_mode();
List<Item> total_list;
res= mysql_select(thd,
@@ -2140,7 +2140,7 @@ int multi_update::send_data(List<Item> &not_used_values)
{
updated--;
if (!ignore ||
- table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
+ table->file->is_fatal_error(error, HA_CHECK_ALL))
{
/*
If (ignore && error == is ignorable) we don't have to
@@ -2148,7 +2148,7 @@ int multi_update::send_data(List<Item> &not_used_values)
*/
myf flags= 0;
- if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
+ if (table->file->is_fatal_error(error, HA_CHECK_ALL))
flags|= ME_FATALERROR; /* Other handler errors are fatal */
prepare_record_for_error_message(error, table);
@@ -2426,7 +2426,7 @@ int multi_update::do_updates()
local_error != HA_ERR_RECORD_IS_THE_SAME)
{
if (!ignore ||
- table->file->is_fatal_error(local_error, HA_CHECK_DUP_KEY))
+ table->file->is_fatal_error(local_error, HA_CHECK_ALL))
{
err_table= table;
goto err;
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index a1483645002..9d7e735fc78 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2015, Oracle and/or its affiliates.
- Copyright (c) 2010, 2015, MariaDB
+ Copyright (c) 2010, 2016, 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
@@ -102,6 +102,9 @@ int yylex(void *yylval, void *yythd);
MYSQL_YYABORT; \
}
+#define my_yyabort_error(A) \
+ do { my_error A; MYSQL_YYABORT; } while(0)
+
#ifndef DBUG_OFF
#define YYDEBUG 1
#else
@@ -1245,7 +1248,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token ENGINES_SYM
%token ENGINE_SYM
%token ENUM
-%token EQ /* OPERATOR */
%token EQUAL_SYM /* OPERATOR */
%token ERROR_SYM
%token ERRORS
@@ -1297,7 +1299,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token GRANTS
%token GROUP_SYM /* SQL-2003-R */
%token GROUP_CONCAT_SYM
-%token GT_SYM /* OPERATOR */
%token HANDLER_SYM
%token HARD_SYM
%token HASH_SYM
@@ -1377,7 +1378,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token LONG_SYM
%token LOOP_SYM
%token LOW_PRIORITY
-%token LT /* OPERATOR */
%token MASTER_CONNECT_RETRY_SYM
%token MASTER_GTID_POS_SYM
%token MASTER_HOST_SYM
@@ -1749,7 +1749,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%left XOR
%left AND_SYM AND_AND_SYM
%left BETWEEN_SYM CASE_SYM WHEN_SYM THEN_SYM ELSE
-%left EQ EQUAL_SYM GE GT_SYM LE LT NE IS LIKE REGEXP IN_SYM
+%left '=' EQUAL_SYM GE '>' LE '<' NE IS LIKE REGEXP IN_SYM
%left '|'
%left '&'
%left SHIFT_LEFT SHIFT_RIGHT
@@ -2110,10 +2110,8 @@ query:
{
if (!thd->bootstrap &&
(!(thd->lex->select_lex.options & OPTION_FOUND_COMMENT)))
- {
- my_message(ER_EMPTY_QUERY, ER_THD(thd, ER_EMPTY_QUERY), MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_EMPTY_QUERY, MYF(0)));
+
thd->lex->sql_command= SQLCOM_EMPTY_QUERY;
YYLIP->found_semicolon= NULL;
}
@@ -2296,10 +2294,7 @@ help:
HELP_SYM
{
if (Lex->sphead)
- {
- my_error(ER_SP_BADSTATEMENT, MYF(0), "HELP");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HELP"));
}
ident_or_text
{
@@ -2326,77 +2321,73 @@ master_defs:
;
master_def:
- MASTER_HOST_SYM EQ TEXT_STRING_sys
+ MASTER_HOST_SYM '=' TEXT_STRING_sys
{
Lex->mi.host = $3.str;
}
- | MASTER_USER_SYM EQ TEXT_STRING_sys
+ | MASTER_USER_SYM '=' TEXT_STRING_sys
{
Lex->mi.user = $3.str;
}
- | MASTER_PASSWORD_SYM EQ TEXT_STRING_sys
+ | MASTER_PASSWORD_SYM '=' TEXT_STRING_sys
{
Lex->mi.password = $3.str;
}
- | MASTER_PORT_SYM EQ ulong_num
+ | MASTER_PORT_SYM '=' ulong_num
{
Lex->mi.port = $3;
}
- | MASTER_CONNECT_RETRY_SYM EQ ulong_num
+ | MASTER_CONNECT_RETRY_SYM '=' ulong_num
{
Lex->mi.connect_retry = $3;
}
- | MASTER_SSL_SYM EQ ulong_num
+ | MASTER_SSL_SYM '=' ulong_num
{
Lex->mi.ssl= $3 ?
LEX_MASTER_INFO::LEX_MI_ENABLE : LEX_MASTER_INFO::LEX_MI_DISABLE;
}
- | MASTER_SSL_CA_SYM EQ TEXT_STRING_sys
+ | MASTER_SSL_CA_SYM '=' TEXT_STRING_sys
{
Lex->mi.ssl_ca= $3.str;
}
- | MASTER_SSL_CAPATH_SYM EQ TEXT_STRING_sys
+ | MASTER_SSL_CAPATH_SYM '=' TEXT_STRING_sys
{
Lex->mi.ssl_capath= $3.str;
}
- | MASTER_SSL_CERT_SYM EQ TEXT_STRING_sys
+ | MASTER_SSL_CERT_SYM '=' TEXT_STRING_sys
{
Lex->mi.ssl_cert= $3.str;
}
- | MASTER_SSL_CIPHER_SYM EQ TEXT_STRING_sys
+ | MASTER_SSL_CIPHER_SYM '=' TEXT_STRING_sys
{
Lex->mi.ssl_cipher= $3.str;
}
- | MASTER_SSL_KEY_SYM EQ TEXT_STRING_sys
+ | MASTER_SSL_KEY_SYM '=' TEXT_STRING_sys
{
Lex->mi.ssl_key= $3.str;
}
- | MASTER_SSL_VERIFY_SERVER_CERT_SYM EQ ulong_num
+ | MASTER_SSL_VERIFY_SERVER_CERT_SYM '=' ulong_num
{
Lex->mi.ssl_verify_server_cert= $3 ?
LEX_MASTER_INFO::LEX_MI_ENABLE : LEX_MASTER_INFO::LEX_MI_DISABLE;
}
- | MASTER_SSL_CRL_SYM EQ TEXT_STRING_sys
+ | MASTER_SSL_CRL_SYM '=' TEXT_STRING_sys
{
Lex->mi.ssl_crl= $3.str;
}
- | MASTER_SSL_CRLPATH_SYM EQ TEXT_STRING_sys
+ | MASTER_SSL_CRLPATH_SYM '=' TEXT_STRING_sys
{
Lex->mi.ssl_crlpath= $3.str;
}
- | MASTER_HEARTBEAT_PERIOD_SYM EQ NUM_literal
+ | MASTER_HEARTBEAT_PERIOD_SYM '=' NUM_literal
{
Lex->mi.heartbeat_period= (float) $3->val_real();
if (Lex->mi.heartbeat_period > SLAVE_MAX_HEARTBEAT_PERIOD ||
Lex->mi.heartbeat_period < 0.0)
- {
- const char format[]= "%d";
- char buf[4*sizeof(SLAVE_MAX_HEARTBEAT_PERIOD) + sizeof(format)];
- sprintf(buf, format, SLAVE_MAX_HEARTBEAT_PERIOD);
- my_error(ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE, MYF(0), buf);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE, MYF(0),
+ SLAVE_MAX_HEARTBEAT_PERIOD));
+
if (Lex->mi.heartbeat_period > slave_net_timeout)
{
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
@@ -2416,15 +2407,15 @@ master_def:
}
Lex->mi.heartbeat_opt= LEX_MASTER_INFO::LEX_MI_ENABLE;
}
- | IGNORE_SERVER_IDS_SYM EQ '(' ignore_server_id_list ')'
+ | IGNORE_SERVER_IDS_SYM '=' '(' ignore_server_id_list ')'
{
Lex->mi.repl_ignore_server_ids_opt= LEX_MASTER_INFO::LEX_MI_ENABLE;
}
- | DO_DOMAIN_IDS_SYM EQ '(' do_domain_id_list ')'
+ | DO_DOMAIN_IDS_SYM '=' '(' do_domain_id_list ')'
{
Lex->mi.repl_do_domain_ids_opt= LEX_MASTER_INFO::LEX_MI_ENABLE;
}
- | IGNORE_DOMAIN_IDS_SYM EQ '(' ignore_domain_id_list ')'
+ | IGNORE_DOMAIN_IDS_SYM '=' '(' ignore_domain_id_list ')'
{
Lex->mi.repl_ignore_domain_ids_opt= LEX_MASTER_INFO::LEX_MI_ENABLE;
}
@@ -2472,11 +2463,11 @@ ignore_domain_id:
;
master_file_def:
- MASTER_LOG_FILE_SYM EQ TEXT_STRING_sys
+ MASTER_LOG_FILE_SYM '=' TEXT_STRING_sys
{
Lex->mi.log_file_name = $3.str;
}
- | MASTER_LOG_POS_SYM EQ ulonglong_num
+ | MASTER_LOG_POS_SYM '=' ulonglong_num
{
/*
If the user specified a value < BIN_LOG_HEADER_SIZE, adjust it
@@ -2491,41 +2482,32 @@ master_file_def:
*/
Lex->mi.pos= MY_MAX(BIN_LOG_HEADER_SIZE, $3);
}
- | RELAY_LOG_FILE_SYM EQ TEXT_STRING_sys
+ | RELAY_LOG_FILE_SYM '=' TEXT_STRING_sys
{
Lex->mi.relay_log_name = $3.str;
}
- | RELAY_LOG_POS_SYM EQ ulong_num
+ | RELAY_LOG_POS_SYM '=' ulong_num
{
Lex->mi.relay_log_pos = $3;
/* Adjust if < BIN_LOG_HEADER_SIZE (same comment as Lex->mi.pos) */
Lex->mi.relay_log_pos= MY_MAX(BIN_LOG_HEADER_SIZE, Lex->mi.relay_log_pos);
}
- | MASTER_USE_GTID_SYM EQ CURRENT_POS_SYM
+ | MASTER_USE_GTID_SYM '=' CURRENT_POS_SYM
{
if (Lex->mi.use_gtid_opt != LEX_MASTER_INFO::LEX_GTID_UNCHANGED)
- {
- my_error(ER_DUP_ARGUMENT, MYF(0), "MASTER_use_gtid");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MASTER_use_gtid"));
Lex->mi.use_gtid_opt= LEX_MASTER_INFO::LEX_GTID_CURRENT_POS;
}
- | MASTER_USE_GTID_SYM EQ SLAVE_POS_SYM
+ | MASTER_USE_GTID_SYM '=' SLAVE_POS_SYM
{
if (Lex->mi.use_gtid_opt != LEX_MASTER_INFO::LEX_GTID_UNCHANGED)
- {
- my_error(ER_DUP_ARGUMENT, MYF(0), "MASTER_use_gtid");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MASTER_use_gtid"));
Lex->mi.use_gtid_opt= LEX_MASTER_INFO::LEX_GTID_SLAVE_POS;
}
- | MASTER_USE_GTID_SYM EQ NO_SYM
+ | MASTER_USE_GTID_SYM '=' NO_SYM
{
if (Lex->mi.use_gtid_opt != LEX_MASTER_INFO::LEX_GTID_UNCHANGED)
- {
- my_error(ER_DUP_ARGUMENT, MYF(0), "MASTER_use_gtid");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MASTER_use_gtid"));
Lex->mi.use_gtid_opt= LEX_MASTER_INFO::LEX_GTID_NO;
}
;
@@ -2545,10 +2527,7 @@ connection_name:
Lex->mi.connection_name= $1;
#ifdef HAVE_REPLICATION
if (check_master_connection_name(&$1))
- {
- my_error(ER_WRONG_ARGUMENTS, MYF(0), "MASTER_CONNECTION_NAME");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_ARGUMENTS, MYF(0), "MASTER_CONNECTION_NAME"));
#endif
}
;
@@ -2859,10 +2838,7 @@ ev_sql_stmt:
- CREATE PROCEDURE ... BEGIN DROP EVENT ... END|
*/
if (lex->sphead)
- {
- my_error(ER_EVENT_RECURSION_FORBIDDEN, MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_EVENT_RECURSION_FORBIDDEN, MYF(0)));
if (!make_sp_head(thd, lex->event_parse_data->identifier, TYPE_ENUM_PROCEDURE))
MYSQL_YYABORT;
@@ -2901,14 +2877,9 @@ sp_name:
ident '.' ident
{
if (!$1.str || check_db_name(&$1))
- {
- my_error(ER_WRONG_DB_NAME, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_DB_NAME, MYF(0), $1.str));
if (check_routine_name(&$3))
- {
MYSQL_YYABORT;
- }
$$= new (thd->mem_root) sp_name($1, $3, true);
if ($$ == NULL)
MYSQL_YYABORT;
@@ -2924,7 +2895,7 @@ sp_name:
}
if (lex->copy_db_to(&db.str, &db.length))
MYSQL_YYABORT;
- $$= new (lex->thd->mem_root) sp_name(db, $1, false);
+ $$= new (thd->mem_root) sp_name(db, $1, false);
if ($$ == NULL)
MYSQL_YYABORT;
$$->init_qname(thd);
@@ -3029,10 +3000,7 @@ sp_param_name_and_type:
sp_pcontext *spc= lex->spcont;
if (spc->find_variable($1, TRUE))
- {
- my_error(ER_SP_DUP_PARAM, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_DUP_PARAM, MYF(0), $1.str));
sp_variable *spvar= spc->add_variable(thd, $1);
@@ -3100,17 +3068,9 @@ sp_decls:
shift/reduce conflicts with the wrong result. (And we get
better error handling this way.) */
if (($2.vars || $2.conds) && ($1.curs || $1.hndlrs))
- { /* Variable or condition following cursor or handler */
- my_message(ER_SP_VARCOND_AFTER_CURSHNDLR,
- ER_THD(thd, ER_SP_VARCOND_AFTER_CURSHNDLR), MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_VARCOND_AFTER_CURSHNDLR, MYF(0)));
if ($2.curs && $1.hndlrs)
- { /* Cursor following handler */
- my_message(ER_SP_CURSOR_AFTER_HANDLER,
- ER_THD(thd, ER_SP_CURSOR_AFTER_HANDLER), MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_CURSOR_AFTER_HANDLER, MYF(0)));
$$.vars= $1.vars + $2.vars;
$$.conds= $1.conds + $2.conds;
$$.hndlrs= $1.hndlrs + $2.hndlrs;
@@ -3175,16 +3135,11 @@ sp_decl:
/* The last instruction is responsible for freeing LEX. */
- sp_instr_set *is= (new (lex->thd->mem_root)
+ sp_instr_set *is= new (lex->thd->mem_root)
sp_instr_set(lex->sphead->instructions(),
- pctx,
- var_idx,
- dflt_value_item,
- $4.field_type(),
- lex,
- last));
- if (is == NULL ||
- lex->sphead->add_instr(is))
+ pctx, var_idx, dflt_value_item,
+ $4.field_type(), lex, last);
+ if (is == NULL || lex->sphead->add_instr(is))
MYSQL_YYABORT;
}
@@ -3200,10 +3155,7 @@ sp_decl:
sp_pcontext *spc= lex->spcont;
if (spc->find_condition($2, TRUE))
- {
- my_error(ER_SP_DUP_COND, MYF(0), $2.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_DUP_COND, MYF(0), $2.str));
if(spc->add_condition(thd, $2, $5))
MYSQL_YYABORT;
$$.vars= $$.hndlrs= $$.curs= 0;
@@ -3222,7 +3174,7 @@ sp_decl:
sp_pcontext *ctx= lex->spcont;
sp_instr_hpush_jump *i=
- new (lex->thd->mem_root) sp_instr_hpush_jump(sp->instructions(),
+ new (thd->mem_root) sp_instr_hpush_jump(sp->instructions(),
ctx, h);
if (i == NULL || sp->add_instr(i))
@@ -3246,7 +3198,7 @@ sp_decl:
if ($2 == sp_handler::CONTINUE)
{
- i= new (lex->thd->mem_root)
+ i= new (thd->mem_root)
sp_instr_hreturn(sp->instructions(), ctx);
if (i == NULL ||
sp->add_instr(i))
@@ -3254,7 +3206,7 @@ sp_decl:
}
else
{ /* EXIT or UNDO handler, just jump to the end of the block */
- i= new (lex->thd->mem_root)
+ i= new (thd->mem_root)
sp_instr_hreturn(sp->instructions(), ctx);
if (i == NULL ||
sp->add_instr(i) ||
@@ -3277,17 +3229,12 @@ sp_decl:
sp_instr_cpush *i;
if (ctx->find_cursor($2, &offp, TRUE))
- {
- my_error(ER_SP_DUP_CURS, MYF(0), $2.str);
- delete $5;
- MYSQL_YYABORT;
- }
- i= new (lex->thd->mem_root)
- sp_instr_cpush(sp->instructions(), ctx, $5,
- ctx->current_cursor_count());
- if (i == NULL ||
- sp->add_instr(i) ||
- ctx->add_cursor($2))
+ my_yyabort_error((ER_SP_DUP_CURS, MYF(0), $2.str));
+
+ i= new (thd->mem_root)
+ sp_instr_cpush(sp->instructions(), ctx, $5,
+ ctx->current_cursor_count());
+ if (i == NULL || sp->add_instr(i) || ctx->add_cursor($2))
MYSQL_YYABORT;
$$.vars= $$.conds= $$.hndlrs= 0;
$$.curs= 1;
@@ -3305,11 +3252,7 @@ sp_cursor_stmt:
DBUG_ASSERT(lex->sql_command == SQLCOM_SELECT);
if (lex->result)
- {
- my_message(ER_SP_BAD_CURSOR_SELECT, ER_THD(thd, ER_SP_BAD_CURSOR_SELECT),
- MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BAD_CURSOR_SELECT, MYF(0)));
lex->sp_lex_in_use= TRUE;
$$= lex;
if (lex->sphead->restore_lex(thd))
@@ -3338,17 +3281,10 @@ sp_hcond_element:
sp_pcontext *ctx= lex->spcont->parent_context();
if (ctx->check_duplicate_handler($1))
- {
- my_message(ER_SP_DUP_HANDLER, ER_THD(thd, ER_SP_DUP_HANDLER), MYF(0));
- MYSQL_YYABORT;
- }
- else
- {
- sp_instr_hpush_jump *i=
- (sp_instr_hpush_jump *)sp->last_instruction();
+ my_yyabort_error((ER_SP_DUP_HANDLER, MYF(0)));
- i->add_condition($1);
- }
+ sp_instr_hpush_jump *i= (sp_instr_hpush_jump *)sp->last_instruction();
+ i->add_condition($1);
}
;
@@ -3356,10 +3292,7 @@ sp_cond:
ulong_num
{ /* mysql errno */
if ($1 == 0)
- {
- my_error(ER_WRONG_VALUE, MYF(0), "CONDITION", "0");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_VALUE, MYF(0), "CONDITION", "0"));
$$= new (thd->mem_root) sp_condition_value($1);
if ($$ == NULL)
MYSQL_YYABORT;
@@ -3379,10 +3312,7 @@ sqlstate:
condition.
*/
if (!is_sqlstate_valid(&$3) || is_sqlstate_completion($3.str))
- {
- my_error(ER_SP_BAD_SQLSTATE, MYF(0), $3.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BAD_SQLSTATE, MYF(0), $3.str));
$$= new (thd->mem_root) sp_condition_value($3.str);
if ($$ == NULL)
MYSQL_YYABORT;
@@ -3403,10 +3333,7 @@ sp_hcond:
{
$$= Lex->spcont->find_condition($1, false);
if ($$ == NULL)
- {
- my_error(ER_SP_COND_MISMATCH, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_COND_MISMATCH, MYF(0), $1.str));
}
| SQLWARNING_SYM /* SQLSTATEs 01??? */
{
@@ -3447,23 +3374,15 @@ signal_value:
{
LEX *lex= Lex;
sp_condition_value *cond;
+
+ /* SIGNAL foo cannot be used outside of stored programs */
if (lex->spcont == NULL)
- {
- /* SIGNAL foo cannot be used outside of stored programs */
- my_error(ER_SP_COND_MISMATCH, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_COND_MISMATCH, MYF(0), $1.str));
cond= lex->spcont->find_condition($1, false);
if (cond == NULL)
- {
- my_error(ER_SP_COND_MISMATCH, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_COND_MISMATCH, MYF(0), $1.str));
if (cond->type != sp_condition_value::SQLSTATE)
- {
- my_error(ER_SIGNAL_BAD_CONDITION_TYPE, MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SIGNAL_BAD_CONDITION_TYPE, MYF(0)));
$$= cond;
}
| sqlstate
@@ -3486,7 +3405,7 @@ opt_set_signal_information:
;
signal_information_item_list:
- signal_condition_information_item_name EQ signal_allowed_expr
+ signal_condition_information_item_name '=' signal_allowed_expr
{
Set_signal_information *info;
info= &thd->m_parser_state->m_yacc.m_set_signal_info;
@@ -3495,17 +3414,14 @@ signal_information_item_list:
info->m_item[index]= $3;
}
| signal_information_item_list ','
- signal_condition_information_item_name EQ signal_allowed_expr
+ signal_condition_information_item_name '=' signal_allowed_expr
{
Set_signal_information *info;
info= &thd->m_parser_state->m_yacc.m_set_signal_info;
int index= (int) $3;
if (info->m_item[index] != NULL)
- {
- my_error(ER_DUP_SIGNAL_SET, MYF(0),
- Diag_condition_item_names[index].str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_DUP_SIGNAL_SET, MYF(0),
+ Diag_condition_item_names[index].str));
info->m_item[index]= $5;
}
;
@@ -3634,7 +3550,7 @@ statement_information:
;
statement_information_item:
- simple_target_specification EQ statement_information_item_name
+ simple_target_specification '=' statement_information_item_name
{
$$= new (thd->mem_root) Statement_information_item($3, $1);
if ($$ == NULL)
@@ -3691,7 +3607,7 @@ condition_information:
;
condition_information_item:
- simple_target_specification EQ condition_information_item_name
+ simple_target_specification '=' condition_information_item_name
{
$$= new (thd->mem_root) Condition_information_item($3, $1);
if ($$ == NULL)
@@ -3736,10 +3652,7 @@ sp_decl_idents:
sp_pcontext *spc= lex->spcont;
if (spc->find_variable($1, TRUE))
- {
- my_error(ER_SP_DUP_VAR, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_DUP_VAR, MYF(0), $1.str));
spc->add_variable(thd, $1);
$$= 1;
}
@@ -3751,10 +3664,7 @@ sp_decl_idents:
sp_pcontext *spc= lex->spcont;
if (spc->find_variable($3, TRUE))
- {
- my_error(ER_SP_DUP_VAR, MYF(0), $3.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_DUP_VAR, MYF(0), $3.str));
spc->add_variable(thd, $3);
$$= $1 + 1;
}
@@ -3825,11 +3735,9 @@ sp_proc_stmt_statement:
sp_head *sp= lex->sphead;
sp->m_flags|= sp_get_flags_for_command(lex);
+ /* "USE db" doesn't work in a procedure */
if (lex->sql_command == SQLCOM_CHANGE_DB)
- { /* "USE db" doesn't work in a procedure */
- my_error(ER_SP_BADSTATEMENT, MYF(0), "USE");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "USE"));
/*
Don't add an instruction for SET statements, since all
instructions for them were already added during processing
@@ -3839,7 +3747,7 @@ sp_proc_stmt_statement:
lex->var_list.is_empty());
if (lex->sql_command != SQLCOM_SET_OPTION)
{
- sp_instr_stmt *i=new (lex->thd->mem_root)
+ sp_instr_stmt *i=new (thd->mem_root)
sp_instr_stmt(sp->instructions(), lex->spcont, lex);
if (i == NULL)
MYSQL_YYABORT;
@@ -3873,22 +3781,17 @@ sp_proc_stmt_return:
sp_head *sp= lex->sphead;
if (sp->m_type != TYPE_ENUM_FUNCTION)
- {
- my_message(ER_SP_BADRETURN, ER_THD(thd, ER_SP_BADRETURN), MYF(0));
- MYSQL_YYABORT;
- }
- else
- {
- sp_instr_freturn *i;
+ my_yyabort_error((ER_SP_BADRETURN, MYF(0)));
+
+ sp_instr_freturn *i;
- i= new (lex->thd->mem_root)
+ i= new (thd->mem_root)
sp_instr_freturn(sp->instructions(), lex->spcont, $3,
sp->m_return_field_def.sql_type, lex);
- if (i == NULL ||
- sp->add_instr(i))
- MYSQL_YYABORT;
- sp->m_flags|= sp_head::HAS_RETURN;
- }
+ if (i == NULL || sp->add_instr(i))
+ MYSQL_YYABORT;
+ sp->m_flags|= sp_head::HAS_RETURN;
+
if (sp->restore_lex(thd))
MYSQL_YYABORT;
}
@@ -3903,49 +3806,44 @@ sp_proc_stmt_leave:
sp_label *lab= ctx->find_label($2);
if (! lab)
+ my_yyabort_error((ER_SP_LILABEL_MISMATCH, MYF(0), "LEAVE", $2.str));
+
+ sp_instr_jump *i;
+ uint ip= sp->instructions();
+ uint n;
+ /*
+ When jumping to a BEGIN-END block end, the target jump
+ points to the block hpop/cpop cleanup instructions,
+ so we should exclude the block context here.
+ When jumping to something else (i.e., SP_LAB_ITER),
+ there are no hpop/cpop at the jump destination,
+ so we should include the block context here for cleanup.
+ */
+ bool exclusive= (lab->type == sp_label::BEGIN);
+
+ n= ctx->diff_handlers(lab->ctx, exclusive);
+ if (n)
{
- my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "LEAVE", $2.str);
- MYSQL_YYABORT;
+ sp_instr_hpop *hpop= new (thd->mem_root)
+ sp_instr_hpop(ip++, ctx, n);
+ if (hpop == NULL)
+ MYSQL_YYABORT;
+ sp->add_instr(hpop);
}
- else
+ n= ctx->diff_cursors(lab->ctx, exclusive);
+ if (n)
{
- sp_instr_jump *i;
- uint ip= sp->instructions();
- uint n;
- /*
- When jumping to a BEGIN-END block end, the target jump
- points to the block hpop/cpop cleanup instructions,
- so we should exclude the block context here.
- When jumping to something else (i.e., SP_LAB_ITER),
- there are no hpop/cpop at the jump destination,
- so we should include the block context here for cleanup.
- */
- bool exclusive= (lab->type == sp_label::BEGIN);
-
- n= ctx->diff_handlers(lab->ctx, exclusive);
- if (n)
- {
- sp_instr_hpop *hpop= new (lex->thd->mem_root)
- sp_instr_hpop(ip++, ctx, n);
- if (hpop == NULL)
- MYSQL_YYABORT;
- sp->add_instr(hpop);
- }
- n= ctx->diff_cursors(lab->ctx, exclusive);
- if (n)
- {
- sp_instr_cpop *cpop= new (lex->thd->mem_root)
- sp_instr_cpop(ip++, ctx, n);
- if (cpop == NULL)
- MYSQL_YYABORT;
- sp->add_instr(cpop);
- }
- i= new (lex->thd->mem_root) sp_instr_jump(ip, ctx);
- if (i == NULL)
+ sp_instr_cpop *cpop= new (thd->mem_root)
+ sp_instr_cpop(ip++, ctx, n);
+ if (cpop == NULL)
MYSQL_YYABORT;
- sp->push_backpatch(thd, i, lab); /* Jumping forward */
- sp->add_instr(i);
+ sp->add_instr(cpop);
}
+ i= new (thd->mem_root) sp_instr_jump(ip, ctx);
+ if (i == NULL)
+ MYSQL_YYABORT;
+ sp->push_backpatch(thd, i, lab); /* Jumping forward */
+ sp->add_instr(i);
}
;
@@ -3958,40 +3856,35 @@ sp_proc_stmt_iterate:
sp_label *lab= ctx->find_label($2);
if (! lab || lab->type != sp_label::ITERATION)
+ my_yyabort_error((ER_SP_LILABEL_MISMATCH, MYF(0), "ITERATE", $2.str));
+
+ sp_instr_jump *i;
+ uint ip= sp->instructions();
+ uint n;
+
+ n= ctx->diff_handlers(lab->ctx, FALSE); /* Inclusive the dest. */
+ if (n)
{
- my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "ITERATE", $2.str);
- MYSQL_YYABORT;
+ sp_instr_hpop *hpop= new (thd->mem_root)
+ sp_instr_hpop(ip++, ctx, n);
+ if (hpop == NULL ||
+ sp->add_instr(hpop))
+ MYSQL_YYABORT;
}
- else
+ n= ctx->diff_cursors(lab->ctx, FALSE); /* Inclusive the dest. */
+ if (n)
{
- sp_instr_jump *i;
- uint ip= sp->instructions();
- uint n;
-
- n= ctx->diff_handlers(lab->ctx, FALSE); /* Inclusive the dest. */
- if (n)
- {
- sp_instr_hpop *hpop= new (lex->thd->mem_root)
- sp_instr_hpop(ip++, ctx, n);
- if (hpop == NULL ||
- sp->add_instr(hpop))
- MYSQL_YYABORT;
- }
- n= ctx->diff_cursors(lab->ctx, FALSE); /* Inclusive the dest. */
- if (n)
- {
- sp_instr_cpop *cpop= new (lex->thd->mem_root)
- sp_instr_cpop(ip++, ctx, n);
- if (cpop == NULL ||
- sp->add_instr(cpop))
- MYSQL_YYABORT;
- }
- i= new (lex->thd->mem_root)
- sp_instr_jump(ip, ctx, lab->ip); /* Jump back */
- if (i == NULL ||
- sp->add_instr(i))
+ sp_instr_cpop *cpop= new (thd->mem_root)
+ sp_instr_cpop(ip++, ctx, n);
+ if (cpop == NULL ||
+ sp->add_instr(cpop))
MYSQL_YYABORT;
}
+ i= new (thd->mem_root)
+ sp_instr_jump(ip, ctx, lab->ip); /* Jump back */
+ if (i == NULL ||
+ sp->add_instr(i))
+ MYSQL_YYABORT;
}
;
@@ -4004,11 +3897,8 @@ sp_proc_stmt_open:
sp_instr_copen *i;
if (! lex->spcont->find_cursor($2, &offset, false))
- {
- my_error(ER_SP_CURSOR_MISMATCH, MYF(0), $2.str);
- MYSQL_YYABORT;
- }
- i= new (lex->thd->mem_root)
+ my_yyabort_error((ER_SP_CURSOR_MISMATCH, MYF(0), $2.str));
+ i= new (thd->mem_root)
sp_instr_copen(sp->instructions(), lex->spcont, offset);
if (i == NULL ||
sp->add_instr(i))
@@ -4025,11 +3915,8 @@ sp_proc_stmt_fetch:
sp_instr_cfetch *i;
if (! lex->spcont->find_cursor($3, &offset, false))
- {
- my_error(ER_SP_CURSOR_MISMATCH, MYF(0), $3.str);
- MYSQL_YYABORT;
- }
- i= new (lex->thd->mem_root)
+ my_yyabort_error((ER_SP_CURSOR_MISMATCH, MYF(0), $3.str));
+ i= new (thd->mem_root)
sp_instr_cfetch(sp->instructions(), lex->spcont, offset);
if (i == NULL ||
sp->add_instr(i))
@@ -4048,11 +3935,8 @@ sp_proc_stmt_close:
sp_instr_cclose *i;
if (! lex->spcont->find_cursor($2, &offset, false))
- {
- my_error(ER_SP_CURSOR_MISMATCH, MYF(0), $2.str);
- MYSQL_YYABORT;
- }
- i= new (lex->thd->mem_root)
+ my_yyabort_error((ER_SP_CURSOR_MISMATCH, MYF(0), $2.str));
+ i= new (thd->mem_root)
sp_instr_cclose(sp->instructions(), lex->spcont, offset);
if (i == NULL ||
sp->add_instr(i))
@@ -4075,17 +3959,11 @@ sp_fetch_list:
sp_variable *spv;
if (!spc || !(spv = spc->find_variable($1, false)))
- {
- my_error(ER_SP_UNDECLARED_VAR, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
- else
- {
- /* An SP local variable */
- sp_instr_cfetch *i= (sp_instr_cfetch *)sp->last_instruction();
+ my_yyabort_error((ER_SP_UNDECLARED_VAR, MYF(0), $1.str));
- i->add_to_varlist(spv);
- }
+ /* An SP local variable */
+ sp_instr_cfetch *i= (sp_instr_cfetch *)sp->last_instruction();
+ i->add_to_varlist(spv);
}
| sp_fetch_list ',' ident
{
@@ -4095,17 +3973,11 @@ sp_fetch_list:
sp_variable *spv;
if (!spc || !(spv = spc->find_variable($3, false)))
- {
- my_error(ER_SP_UNDECLARED_VAR, MYF(0), $3.str);
- MYSQL_YYABORT;
- }
- else
- {
- /* An SP local variable */
- sp_instr_cfetch *i= (sp_instr_cfetch *)sp->last_instruction();
+ my_yyabort_error((ER_SP_UNDECLARED_VAR, MYF(0), $3.str));
- i->add_to_varlist(spv);
- }
+ /* An SP local variable */
+ sp_instr_cfetch *i= (sp_instr_cfetch *)sp->last_instruction();
+ i->add_to_varlist(spv);
}
;
@@ -4117,7 +3989,7 @@ sp_if:
sp_head *sp= lex->sphead;
sp_pcontext *ctx= lex->spcont;
uint ip= sp->instructions();
- sp_instr_jump_if_not *i= new (lex->thd->mem_root)
+ sp_instr_jump_if_not *i= new (thd->mem_root)
sp_instr_jump_if_not(ip, ctx, $2, lex);
if (i == NULL ||
sp->push_backpatch(thd, i, ctx->push_label(thd, empty_lex_str, 0)) ||
@@ -4325,10 +4197,7 @@ sp_labeled_block:
sp_label *lab= ctx->find_label($1);
if (lab)
- {
- my_error(ER_SP_LABEL_REDEFINE, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_LABEL_REDEFINE, MYF(0), $1.str));
lex->name= $1;
}
sp_block_content sp_opt_label
@@ -4336,10 +4205,7 @@ sp_labeled_block:
if ($6.str)
{
if (my_strcasecmp(system_charset_info, $6.str, $5->name.str) != 0)
- {
- my_error(ER_SP_LABEL_MISMATCH, MYF(0), $6.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_LABEL_MISMATCH, MYF(0), $6.str));
}
}
;
@@ -4393,7 +4259,7 @@ sp_block_content:
}
if ($2.curs)
{
- i= new (lex->thd->mem_root)
+ i= new (thd->mem_root)
sp_instr_cpop(sp->instructions(), ctx, $2.curs);
if (i == NULL ||
sp->add_instr(i))
@@ -4410,7 +4276,7 @@ loop_body:
LEX *lex= Lex;
uint ip= lex->sphead->instructions();
sp_label *lab= lex->spcont->last_label(); /* Jumping back */
- sp_instr_jump *i= new (lex->thd->mem_root)
+ sp_instr_jump *i= new (thd->mem_root)
sp_instr_jump(ip, lex->spcont, lab->ip);
if (i == NULL ||
lex->sphead->add_instr(i))
@@ -4424,7 +4290,7 @@ while_body:
LEX *lex= Lex;
sp_head *sp= lex->sphead;
uint ip= sp->instructions();
- sp_instr_jump_if_not *i= new (lex->thd->mem_root)
+ sp_instr_jump_if_not *i= new (thd->mem_root)
sp_instr_jump_if_not(ip, lex->spcont, $1, lex);
if (i == NULL ||
/* Jumping forward */
@@ -4440,7 +4306,7 @@ while_body:
LEX *lex= Lex;
uint ip= lex->sphead->instructions();
sp_label *lab= lex->spcont->last_label(); /* Jumping back */
- sp_instr_jump *i= new (lex->thd->mem_root)
+ sp_instr_jump *i= new (thd->mem_root)
sp_instr_jump(ip, lex->spcont, lab->ip);
if (i == NULL ||
lex->sphead->add_instr(i))
@@ -4457,7 +4323,7 @@ repeat_body:
LEX *lex= Lex;
uint ip= lex->sphead->instructions();
sp_label *lab= lex->spcont->last_label(); /* Jumping back */
- sp_instr_jump_if_not *i= new (lex->thd->mem_root)
+ sp_instr_jump_if_not *i= new (thd->mem_root)
sp_instr_jump_if_not(ip, lex->spcont, $4, lab->ip, lex);
if (i == NULL ||
lex->sphead->add_instr(i))
@@ -4478,10 +4344,7 @@ pop_sp_label:
{
if (my_strcasecmp(system_charset_info, $1.str,
lab->name.str) != 0)
- {
- my_error(ER_SP_LABEL_MISMATCH, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_LABEL_MISMATCH, MYF(0), $1.str));
}
}
;
@@ -4848,10 +4711,7 @@ opt_ts_nodegroup:
{
LEX *lex= Lex;
if (lex->alter_tablespace_info->nodegroup_id != UNDEF_NODEGROUP)
- {
- my_error(ER_FILEGROUP_OPTION_ONLY_ONCE,MYF(0),"NODEGROUP");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_FILEGROUP_OPTION_ONLY_ONCE,MYF(0),"NODEGROUP"));
lex->alter_tablespace_info->nodegroup_id= $3;
}
;
@@ -4861,10 +4721,7 @@ opt_ts_comment:
{
LEX *lex= Lex;
if (lex->alter_tablespace_info->ts_comment != NULL)
- {
- my_error(ER_FILEGROUP_OPTION_ONLY_ONCE,MYF(0),"COMMENT");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_FILEGROUP_OPTION_ONLY_ONCE,MYF(0),"COMMENT"));
lex->alter_tablespace_info->ts_comment= $3.str;
}
;
@@ -4874,11 +4731,8 @@ opt_ts_engine:
{
LEX *lex= Lex;
if (lex->alter_tablespace_info->storage_engine != NULL)
- {
- my_error(ER_FILEGROUP_OPTION_ONLY_ONCE,MYF(0),
- "STORAGE ENGINE");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_FILEGROUP_OPTION_ONLY_ONCE, MYF(0),
+ "STORAGE ENGINE"));
lex->alter_tablespace_info->storage_engine= $4;
}
;
@@ -4898,10 +4752,7 @@ ts_wait:
{
LEX *lex= Lex;
if (!(lex->alter_tablespace_info->wait_until_completed))
- {
- my_error(ER_FILEGROUP_OPTION_ONLY_ONCE,MYF(0),"NO_WAIT");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_FILEGROUP_OPTION_ONLY_ONCE,MYF(0),"NO_WAIT"));
lex->alter_tablespace_info->wait_until_completed= FALSE;
}
;
@@ -4933,23 +4784,14 @@ size_number:
text_shift_number+=10;
break;
default:
- {
- my_error(ER_WRONG_SIZE_NUMBER, MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_SIZE_NUMBER, MYF(0)));
}
if (prefix_number >> 31)
- {
- my_error(ER_SIZE_OVERFLOW_ERROR, MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SIZE_OVERFLOW_ERROR, MYF(0)));
number= prefix_number << text_shift_number;
}
else
- {
- my_error(ER_WRONG_SIZE_NUMBER, MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_SIZE_NUMBER, MYF(0)));
$$= number;
}
;
@@ -5076,15 +4918,11 @@ have_partitioning:
#ifdef WITH_PARTITION_STORAGE_ENGINE
LEX_STRING partition_name={C_STRING_WITH_LEN("partition")};
if (!plugin_is_ready(&partition_name, MYSQL_STORAGE_ENGINE_PLUGIN))
- {
- my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0),
- "--skip-partition");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_OPTION_PREVENTS_STATEMENT, MYF(0),
+ "--skip-partition"));
#else
- my_error(ER_FEATURE_DISABLED, MYF(0), "partitioning",
- "--with-plugin-partition");
- MYSQL_YYABORT;
+ my_yyabort_error((ER_FEATURE_DISABLED, MYF(0), "partitioning",
+ "--with-plugin-partition"));
#endif
}
;
@@ -5142,7 +4980,7 @@ opt_linear:
opt_key_algo:
/* empty */
{ Lex->part_info->key_algorithm= partition_info::KEY_ALGORITHM_NONE;}
- | ALGORITHM_SYM EQ real_ulong_num
+ | ALGORITHM_SYM '=' real_ulong_num
{
switch ($3) {
case 1:
@@ -5179,11 +5017,8 @@ part_field_item:
MYSQL_YYABORT;
}
if (part_info->num_columns > MAX_REF_PARTS)
- {
- my_error(ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR, MYF(0),
- "list of partition fields");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR, MYF(0),
+ "list of partition fields"));
}
;
@@ -5224,10 +5059,7 @@ opt_num_parts:
uint num_parts= $2;
partition_info *part_info= Lex->part_info;
if (num_parts == 0)
- {
- my_error(ER_NO_PARTS_ERROR, MYF(0), "partitions");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_NO_PARTS_ERROR, MYF(0), "partitions"));
part_info->num_parts= num_parts;
part_info->use_default_num_partitions= FALSE;
@@ -5264,11 +5096,8 @@ sub_part_field_item:
MYSQL_YYABORT;
}
if (part_info->subpart_field_list.elements > MAX_REF_PARTS)
- {
- my_error(ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR, MYF(0),
- "list of subpartition fields");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR, MYF(0),
+ "list of subpartition fields"));
}
;
@@ -5291,10 +5120,7 @@ opt_num_subparts:
uint num_parts= $2;
LEX *lex= Lex;
if (num_parts == 0)
- {
- my_error(ER_NO_PARTS_ERROR, MYF(0), "subpartitions");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_NO_PARTS_ERROR, MYF(0), "subpartitions"));
lex->part_info->num_subparts= num_parts;
lex->part_info->use_default_num_subpartitions= FALSE;
}
@@ -5305,17 +5131,11 @@ part_defs:
{
partition_info *part_info= Lex->part_info;
if (part_info->part_type == RANGE_PARTITION)
- {
- my_error(ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0),
- "RANGE");
- MYSQL_YYABORT;
- }
- else if (part_info->part_type == LIST_PARTITION)
- {
- my_error(ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0),
- "LIST");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0),
+ "RANGE"));
+ if (part_info->part_type == LIST_PARTITION)
+ my_yyabort_error((ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0),
+ "LIST"));
}
| '(' part_def_list ')'
{
@@ -5385,17 +5205,11 @@ opt_part_values:
if (! lex->is_partition_management())
{
if (part_info->part_type == RANGE_PARTITION)
- {
- my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
- "RANGE", "LESS THAN");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
+ "RANGE", "LESS THAN"));
if (part_info->part_type == LIST_PARTITION)
- {
- my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
- "LIST", "IN");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
+ "LIST", "IN"));
}
else
part_info->part_type= HASH_PARTITION;
@@ -5407,11 +5221,8 @@ opt_part_values:
if (! lex->is_partition_management())
{
if (part_info->part_type != RANGE_PARTITION)
- {
- my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
- "RANGE", "LESS THAN");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
+ "RANGE", "LESS THAN"));
}
else
part_info->part_type= RANGE_PARTITION;
@@ -5424,11 +5235,8 @@ opt_part_values:
if (! lex->is_partition_management())
{
if (part_info->part_type != LIST_PARTITION)
- {
- my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
- "LIST", "IN");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
+ "LIST", "IN"));
}
else
part_info->part_type= LIST_PARTITION;
@@ -6042,12 +5850,16 @@ create_table_option:
}
| IDENT_sys equal TEXT_STRING_sys
{
+ if ($3.length > ENGINE_OPTION_MAX_LENGTH)
+ my_yyabort_error((ER_VALUE_TOO_LONG, MYF(0), $1.str));
new (thd->mem_root)
engine_option_value($1, $3, true, &Lex->create_info.option_list,
&Lex->option_list_last);
}
| IDENT_sys equal ident
{
+ if ($3.length > ENGINE_OPTION_MAX_LENGTH)
+ my_yyabort_error((ER_VALUE_TOO_LONG, MYF(0), $1.str));
new (thd->mem_root)
engine_option_value($1, $3, false, &Lex->create_info.option_list,
&Lex->option_list_last);
@@ -6102,10 +5914,7 @@ storage_engines:
else
{
if (thd->variables.sql_mode & MODE_NO_ENGINE_SUBSTITUTION)
- {
- my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_UNKNOWN_STORAGE_ENGINE, MYF(0), $1.str));
$$= 0;
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_UNKNOWN_STORAGE_ENGINE,
@@ -6122,10 +5931,7 @@ known_storage_engines:
if ((plugin= ha_resolve_by_name(thd, &$1, false)))
$$= plugin_hton(plugin);
else
- {
- my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_UNKNOWN_STORAGE_ENGINE, MYF(0), $1.str));
}
;
@@ -6303,10 +6109,7 @@ field_spec:
if (check_string_char_length(&$1, 0, NAME_CHAR_LEN,
system_charset_info, 1))
- {
- my_error(ER_TOO_LONG_IDENT, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_TOO_LONG_IDENT, MYF(0), $1.str));
if (!f)
MYSQL_YYABORT;
@@ -6461,12 +6264,9 @@ field_type:
int err;
ulonglong tmp_length= my_strtoll10($2.length(), NULL, &err);
if (err || tmp_length > PRECISION_FOR_DOUBLE)
- {
- my_error(ER_WRONG_FIELD_SPEC, MYF(0),
- Lex->last_field->field_name);
- MYSQL_YYABORT;
- }
- else if (tmp_length > PRECISION_FOR_FLOAT)
+ my_yyabort_error((ER_WRONG_FIELD_SPEC, MYF(0),
+ Lex->last_field->field_name));
+ if (tmp_length > PRECISION_FOR_FLOAT)
$$.set(MYSQL_TYPE_DOUBLE);
else
$$.set(MYSQL_TYPE_FLOAT);
@@ -6572,9 +6372,8 @@ field_type:
Lex->last_field->geom_type= $1;
$$.set(MYSQL_TYPE_GEOMETRY, $2);
#else
- my_error(ER_FEATURE_DISABLED, MYF(0),
- sym_group_geom.name, sym_group_geom.needed_define);
- MYSQL_YYABORT;
+ my_yyabort_error((ER_FEATURE_DISABLED, MYF(0), sym_group_geom.name,
+ sym_group_geom.needed_define));
#endif
}
| MEDIUMBLOB
@@ -6679,7 +6478,7 @@ srid_option:
/* empty */
{ Lex->last_field->srid= 0; }
|
- REF_SYSTEM_ID_SYM EQ NUM
+ REF_SYSTEM_ID_SYM '=' NUM
{
Lex->last_field->srid=atoi($3.str);
}
@@ -6780,24 +6579,22 @@ attribute:
| COLLATE_SYM collation_name
{
if (Lex->charset && !my_charset_same(Lex->charset,$2))
- {
- my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
- $2->name,Lex->charset->csname);
- MYSQL_YYABORT;
- }
- else
- {
- Lex->last_field->charset= $2;
- }
+ my_yyabort_error((ER_COLLATION_CHARSET_MISMATCH, MYF(0),
+ $2->name,Lex->charset->csname));
+ Lex->last_field->charset= $2;
}
| IDENT_sys equal TEXT_STRING_sys
{
+ if ($3.length > ENGINE_OPTION_MAX_LENGTH)
+ my_yyabort_error((ER_VALUE_TOO_LONG, MYF(0), $1.str));
new (thd->mem_root)
engine_option_value($1, $3, true, &Lex->last_field->option_list,
&Lex->option_list_last);
}
| IDENT_sys equal ident
{
+ if ($3.length > ENGINE_OPTION_MAX_LENGTH)
+ my_yyabort_error((ER_VALUE_TOO_LONG, MYF(0), $1.str));
new (thd->mem_root)
engine_option_value($1, $3, false, &Lex->last_field->option_list,
&Lex->option_list_last);
@@ -6839,10 +6636,7 @@ charset_name:
ident_or_text
{
if (!($$=get_charset_by_csname($1.str,MY_CS_PRIMARY,MYF(0))))
- {
- my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_UNKNOWN_CHARACTER_SET, MYF(0), $1.str));
}
| BINARY { $$= &my_charset_bin; }
;
@@ -6862,10 +6656,7 @@ old_or_new_charset_name:
{
if (!($$=get_charset_by_csname($1.str,MY_CS_PRIMARY,MYF(0))) &&
!($$=get_old_charset_by_name($1.str)))
- {
- my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_UNKNOWN_CHARACTER_SET, MYF(0), $1.str));
}
| BINARY { $$= &my_charset_bin; }
;
@@ -6904,10 +6695,7 @@ charset_or_alias:
| UNICODE_SYM
{
if (!($$= get_charset_by_csname("ucs2", MY_CS_PRIMARY,MYF(0))))
- {
- my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), "ucs2");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_UNKNOWN_CHARACTER_SET, MYF(0), "ucs2"));
}
;
@@ -7123,9 +6911,8 @@ spatial:
#ifdef HAVE_SPATIAL
$$= Key::SPATIAL;
#else
- my_error(ER_FEATURE_DISABLED, MYF(0),
- sym_group_geom.name, sym_group_geom.needed_define);
- MYSQL_YYABORT;
+ my_yyabort_error((ER_FEATURE_DISABLED, MYF(0), sym_group_geom.name,
+ sym_group_geom.needed_define));
#endif
}
;
@@ -7184,12 +6971,16 @@ all_key_opt:
{ Lex->last_key->key_create_info.comment= $2; }
| IDENT_sys equal TEXT_STRING_sys
{
+ if ($3.length > ENGINE_OPTION_MAX_LENGTH)
+ my_yyabort_error((ER_VALUE_TOO_LONG, MYF(0), $1.str));
new (thd->mem_root)
engine_option_value($1, $3, true, &Lex->option_list,
&Lex->option_list_last);
}
| IDENT_sys equal ident
{
+ if ($3.length > ENGINE_OPTION_MAX_LENGTH)
+ my_yyabort_error((ER_VALUE_TOO_LONG, MYF(0), $1.str));
new (thd->mem_root)
engine_option_value($1, $3, false, &Lex->option_list,
&Lex->option_list_last);
@@ -7223,10 +7014,7 @@ fulltext_key_opt:
if (plugin_is_ready(&$3, MYSQL_FTPARSER_PLUGIN))
Lex->last_key->key_create_info.parser_name= $3;
else
- {
- my_error(ER_FUNCTION_NOT_DEFINED, MYF(0), $3.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_FUNCTION_NOT_DEFINED, MYF(0), $3.str));
}
;
@@ -7258,9 +7046,7 @@ key_part:
{
int key_part_len= atoi($3.str);
if (!key_part_len)
- {
- my_error(ER_KEY_PART_0, MYF(0), $1.str);
- }
+ my_yyabort_error((ER_KEY_PART_0, MYF(0), $1.str));
$$= new (thd->mem_root) Key_part_spec($1, (uint) key_part_len);
if ($$ == NULL)
MYSQL_YYABORT;
@@ -7340,10 +7126,7 @@ alter:
{
LEX *lex= Lex;
if (lex->sphead)
- {
- my_error(ER_SP_NO_DROP_SP, MYF(0), "DATABASE");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "DATABASE"));
lex->sql_command= SQLCOM_ALTER_DB_UPGRADE;
lex->name= $3;
}
@@ -7352,10 +7135,7 @@ alter:
LEX *lex= Lex;
if (lex->sphead)
- {
- my_error(ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE"));
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
}
sp_a_chistics
@@ -7370,10 +7150,7 @@ alter:
LEX *lex= Lex;
if (lex->sphead)
- {
- my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "FUNCTION"));
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
}
sp_a_chistics
@@ -7388,10 +7165,7 @@ alter:
LEX *lex= Lex;
if (lex->sphead)
- {
- my_error(ER_SP_BADSTATEMENT, MYF(0), "ALTER VIEW");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "ALTER VIEW"));
lex->create_view_mode= VIEW_ALTER;
}
view_tail
@@ -7406,10 +7180,7 @@ alter:
LEX *lex= Lex;
if (lex->sphead)
- {
- my_error(ER_SP_BADSTATEMENT, MYF(0), "ALTER VIEW");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "ALTER VIEW"));
lex->create_view_algorithm= VIEW_ALGORITHM_INHERIT;
lex->create_view_mode= VIEW_ALTER;
}
@@ -7897,10 +7668,7 @@ alter_list_item:
}
if (check_table_name($3->table.str,$3->table.length, FALSE) ||
($3->db.str && check_db_name(&$3->db)))
- {
- my_error(ER_WRONG_TABLE_NAME, MYF(0), $3->table.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_TABLE_NAME, MYF(0), $3->table.str));
lex->name= $3->table;
lex->alter_info.flags|= Alter_info::ALTER_RENAME;
}
@@ -7912,15 +7680,11 @@ alter_list_item:
}
$5= $5 ? $5 : $4;
if (!my_charset_same($4,$5))
- {
- my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
- $5->name, $4->csname);
+ my_yyabort_error((ER_COLLATION_CHARSET_MISMATCH, MYF(0),
+ $5->name, $4->csname));
+ if (Lex->create_info.add_alter_list_item_convert_to_charset($5))
MYSQL_YYABORT;
- }
- LEX *lex= Lex;
- if (lex->create_info.add_alter_list_item_convert_to_charset($5))
- MYSQL_YYABORT;
- lex->alter_info.flags|= Alter_info::ALTER_CONVERT;
+ Lex->alter_info.flags|= Alter_info::ALTER_CONVERT;
}
| create_table_options_space_separated
{
@@ -7961,10 +7725,7 @@ alter_algorithm_option:
| ALGORITHM_SYM opt_equal ident
{
if (Lex->alter_info.set_requested_algorithm(&$3))
- {
- my_error(ER_UNKNOWN_ALTER_ALGORITHM, MYF(0), $3.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_UNKNOWN_ALTER_ALGORITHM, MYF(0), $3.str));
}
;
@@ -7977,10 +7738,7 @@ alter_lock_option:
| LOCK_SYM opt_equal ident
{
if (Lex->alter_info.set_requested_lock(&$3))
- {
- my_error(ER_UNKNOWN_ALTER_LOCK, MYF(0), $3.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_UNKNOWN_ALTER_LOCK, MYF(0), $3.str));
}
;
@@ -8040,7 +7798,7 @@ opt_place:
opt_to:
/* empty */ {}
| TO_SYM {}
- | EQ {}
+ | '=' {}
| AS {}
;
@@ -8156,13 +7914,9 @@ slave_until:
(lex->mi.relay_log_name || lex->mi.relay_log_pos)) ||
!((lex->mi.log_file_name && lex->mi.pos) ||
(lex->mi.relay_log_name && lex->mi.relay_log_pos)))
- {
- my_message(ER_BAD_SLAVE_UNTIL_COND,
- ER_THD(thd, ER_BAD_SLAVE_UNTIL_COND), MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_BAD_SLAVE_UNTIL_COND, MYF(0)));
}
- | UNTIL_SYM MASTER_GTID_POS_SYM EQ TEXT_STRING_sys
+ | UNTIL_SYM MASTER_GTID_POS_SYM '=' TEXT_STRING_sys
{
Lex->mi.gtid_pos_str = $4;
}
@@ -8375,10 +8129,7 @@ check: CHECK_SYM
{
LEX* lex= thd->lex;
if (lex->sphead)
- {
- my_error(ER_SP_BADSTATEMENT, MYF(0), "CHECK");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "CHECK"));
DBUG_ASSERT(!lex->m_sql_cmd);
lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_check_table();
if (lex->m_sql_cmd == NULL)
@@ -8475,9 +8226,9 @@ table_to_table:
{
LEX *lex=Lex;
SELECT_LEX *sl= lex->current_select;
- if (!sl->add_table_to_list(lex->thd, $1,NULL,TL_OPTION_UPDATING,
+ if (!sl->add_table_to_list(thd, $1,NULL,TL_OPTION_UPDATING,
TL_IGNORE, MDL_EXCLUSIVE) ||
- !sl->add_table_to_list(lex->thd, $3,NULL,TL_OPTION_UPDATING,
+ !sl->add_table_to_list(thd, $3,NULL,TL_OPTION_UPDATING,
TL_IGNORE, MDL_EXCLUSIVE))
MYSQL_YYABORT;
}
@@ -8839,10 +8590,7 @@ select_options:
| select_option_list
{
if (Select->options & SELECT_DISTINCT && Select->options & SELECT_ALL)
- {
- my_error(ER_WRONG_USAGE, MYF(0), "ALL", "DISTINCT");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0), "ALL", "DISTINCT"));
}
;
@@ -8860,26 +8608,15 @@ select_option:
SQL_CACHE wasn't specified, and only once per query.
*/
if (Lex->current_select != &Lex->select_lex)
- {
- my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_NO_CACHE");
- MYSQL_YYABORT;
- }
- else if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE)
- {
- my_error(ER_WRONG_USAGE, MYF(0), "SQL_CACHE", "SQL_NO_CACHE");
- MYSQL_YYABORT;
- }
- else if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE)
- {
- my_error(ER_DUP_ARGUMENT, MYF(0), "SQL_NO_CACHE");
- MYSQL_YYABORT;
- }
- else
- {
- Lex->safe_to_cache_query=0;
- Lex->select_lex.options&= ~OPTION_TO_QUERY_CACHE;
- Lex->select_lex.sql_cache= SELECT_LEX::SQL_NO_CACHE;
- }
+ my_yyabort_error((ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_NO_CACHE"));
+ if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE)
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0), "SQL_CACHE", "SQL_NO_CACHE"));
+ if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE)
+ my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "SQL_NO_CACHE"));
+
+ Lex->safe_to_cache_query=0;
+ Lex->select_lex.options&= ~OPTION_TO_QUERY_CACHE;
+ Lex->select_lex.sql_cache= SELECT_LEX::SQL_NO_CACHE;
}
| SQL_CACHE_SYM
{
@@ -8888,26 +8625,15 @@ select_option:
SQL_NO_CACHE wasn't specified, and only once per query.
*/
if (Lex->current_select != &Lex->select_lex)
- {
- my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_CACHE");
- MYSQL_YYABORT;
- }
- else if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE)
- {
- my_error(ER_WRONG_USAGE, MYF(0), "SQL_NO_CACHE", "SQL_CACHE");
- MYSQL_YYABORT;
- }
- else if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE)
- {
- my_error(ER_DUP_ARGUMENT, MYF(0), "SQL_CACHE");
- MYSQL_YYABORT;
- }
- else
- {
- Lex->safe_to_cache_query=1;
- Lex->select_lex.options|= OPTION_TO_QUERY_CACHE;
- Lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE;
- }
+ my_yyabort_error((ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_CACHE"));
+ if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE)
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0), "SQL_NO_CACHE", "SQL_CACHE"));
+ if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE)
+ my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "SQL_CACHE"));
+
+ Lex->safe_to_cache_query=1;
+ Lex->select_lex.options|= OPTION_TO_QUERY_CACHE;
+ Lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE;
}
;
@@ -8960,10 +8686,7 @@ select_item:
{
if (Lex->sql_command == SQLCOM_CREATE_VIEW &&
check_column_name($4.str))
- {
- my_error(ER_WRONG_COLUMN_NAME, MYF(0), $4.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_COLUMN_NAME, MYF(0), $4.str));
$2->is_autogenerated_name= FALSE;
$2->set_name(thd, $4.str, $4.length, system_charset_info);
}
@@ -9190,13 +8913,13 @@ bool_pri:
if ($$ == NULL)
MYSQL_YYABORT;
}
- | bool_pri comp_op predicate %prec EQ
+ | bool_pri comp_op predicate %prec '='
{
$$= (*$2)(0)->create(thd, $1, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
- | bool_pri comp_op all_or_any '(' subselect ')' %prec EQ
+ | bool_pri comp_op all_or_any '(' subselect ')' %prec '='
{
$$= all_any_subquery_creator(thd, $1, $2, $3, $5);
if ($$ == NULL)
@@ -9420,11 +9143,11 @@ not2:
;
comp_op:
- EQ { $$ = &comp_eq_creator; }
+ '=' { $$ = &comp_eq_creator; }
| GE { $$ = &comp_ge_creator; }
- | GT_SYM { $$ = &comp_gt_creator; }
+ | '>' { $$ = &comp_gt_creator; }
| LE { $$ = &comp_le_creator; }
- | LT { $$ = &comp_lt_creator; }
+ | '<' { $$ = &comp_lt_creator; }
| NE { $$ = &comp_ne_creator; }
;
@@ -9631,11 +9354,7 @@ column_default_non_parenthesized_expr:
{
Item_splocal *il= $3->get_item_splocal();
if (il)
- {
-
- my_error(ER_WRONG_COLUMN_NAME, MYF(0), il->my_name()->str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_COLUMN_NAME, MYF(0), il->my_name()->str));
$$= new (thd->mem_root) Item_default_value(thd, Lex->current_context(),
$3);
if ($$ == NULL)
@@ -10302,9 +10021,8 @@ function_call_conflict:
if ($$ == NULL)
MYSQL_YYABORT;
#else
- my_error(ER_FEATURE_DISABLED, MYF(0),
- sym_group_geom.name, sym_group_geom.needed_define);
- MYSQL_YYABORT;
+ my_yyabort_error((ER_FEATURE_DISABLED, MYF(0), sym_group_geom.name,
+ sym_group_geom.needed_define));
#endif
}
;
@@ -10466,10 +10184,7 @@ function_call_generic:
*/
if (!$1.str || check_db_name(&$1))
- {
- my_error(ER_WRONG_DB_NAME, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_DB_NAME, MYF(0), $1.str));
if (check_routine_name(&$3))
{
MYSQL_YYABORT;
@@ -10779,10 +10494,7 @@ variable:
'@'
{
if (! Lex->parsing_options.allows_variable)
- {
- my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_VIEW_SELECT_VARIABLE, MYF(0)));
}
variable_aux
{
@@ -10974,7 +10686,7 @@ table_ref:
| join_table
{
LEX *lex= Lex;
- if (!($$= lex->current_select->nest_last_join(lex->thd)))
+ if (!($$= lex->current_select->nest_last_join(thd)))
{
my_parse_error(thd, ER_SYNTAX_ERROR);
MYSQL_YYABORT;
@@ -11237,7 +10949,7 @@ table_primary_derived:
Table_ident *ti= new (thd->mem_root) Table_ident(unit);
if (ti == NULL)
MYSQL_YYABORT;
- if (!($$= sel->add_table_to_list(lex->thd,
+ if (!($$= sel->add_table_to_list(thd,
ti, $5, 0,
TL_READ, MDL_SHARED_READ)))
@@ -11592,7 +11304,7 @@ date_time_type:
table_alias:
/* empty */
| AS
- | EQ
+ | '='
;
opt_table_alias:
@@ -11688,14 +11400,11 @@ olap_opt:
*/
LEX *lex=Lex;
if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
- {
- my_error(ER_WRONG_USAGE, MYF(0), "WITH CUBE",
- "global union parameters");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0), "WITH CUBE",
+ "global union parameters"));
lex->current_select->olap= CUBE_TYPE;
- my_error(ER_NOT_SUPPORTED_YET, MYF(0), "CUBE");
- MYSQL_YYABORT;
+
+ my_yyabort_error((ER_NOT_SUPPORTED_YET, MYF(0), "CUBE"));
}
| WITH_ROLLUP_SYM
{
@@ -11708,11 +11417,8 @@ olap_opt:
*/
LEX *lex= Lex;
if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
- {
- my_error(ER_WRONG_USAGE, MYF(0), "WITH ROLLUP",
- "global union parameters");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0), "WITH ROLLUP",
+ "global union parameters"));
lex->current_select->olap= ROLLUP_TYPE;
}
;
@@ -11926,7 +11632,7 @@ order_clause:
if (!unit->is_union() &&
(first_sl->order_list.elements ||
first_sl->select_limit) &&
- unit->add_fake_select_lex(lex->thd))
+ unit->add_fake_select_lex(thd))
MYSQL_YYABORT;
}
if (sel->master_unit()->is_union() && !sel->braces)
@@ -12043,15 +11749,9 @@ limit_option:
lex->safe_to_cache_query=0;
}
else
- {
- my_error(ER_SP_UNDECLARED_VAR, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_UNDECLARED_VAR, MYF(0), $1.str));
if (splocal->type() != Item::INT_ITEM)
- {
- my_error(ER_WRONG_SPVAR_TYPE_IN_LIMIT, MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_SPVAR_TYPE_IN_LIMIT, MYF(0)));
splocal->limit_clause_param= TRUE;
$$= splocal;
}
@@ -12172,7 +11872,7 @@ procedure_clause:
NULL, NULL, $2.str);
if (item == NULL)
MYSQL_YYABORT;
- if (add_proc_to_list(lex->thd, item))
+ if (add_proc_to_list(thd, item))
MYSQL_YYABORT;
Lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
@@ -12256,10 +11956,7 @@ select_outvar:
sp_variable *t;
if (!Lex->spcont || !(t= Lex->spcont->find_variable($1, false)))
- {
- my_error(ER_SP_UNDECLARED_VAR, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_UNDECLARED_VAR, MYF(0), $1.str));
$$ = Lex->result ? (new (thd->mem_root)
my_var_sp($1, t->offset, t->sql_type(),
Lex->sphead)) :
@@ -12346,7 +12043,7 @@ drop:
lex->alter_info.reset();
lex->alter_info.flags= Alter_info::ALTER_DROP_INDEX;
lex->alter_info.drop_list.push_back(ad, thd->mem_root);
- if (!lex->current_select->add_table_to_list(lex->thd, $6, NULL,
+ if (!lex->current_select->add_table_to_list(thd, $6, NULL,
TL_OPTION_UPDATING,
TL_READ_NO_INSERT,
MDL_SHARED_UPGRADABLE))
@@ -12363,17 +12060,11 @@ drop:
LEX *lex= thd->lex;
sp_name *spname;
if ($4.str && check_db_name(&$4))
- {
- my_error(ER_WRONG_DB_NAME, MYF(0), $4.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_DB_NAME, MYF(0), $4.str));
if (lex->sphead)
- {
- my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "FUNCTION"));
lex->set_command(SQLCOM_DROP_FUNCTION, $3);
- spname= new (lex->thd->mem_root) sp_name($4, $6, true);
+ spname= new (thd->mem_root) sp_name($4, $6, true);
if (spname == NULL)
MYSQL_YYABORT;
spname->init_qname(thd);
@@ -12385,14 +12076,11 @@ drop:
LEX_STRING db= {0, 0};
sp_name *spname;
if (lex->sphead)
- {
- my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "FUNCTION"));
if (thd->db && lex->copy_db_to(&db.str, &db.length))
MYSQL_YYABORT;
lex->set_command(SQLCOM_DROP_FUNCTION, $3);
- spname= new (lex->thd->mem_root) sp_name(db, $4, false);
+ spname= new (thd->mem_root) sp_name(db, $4, false);
if (spname == NULL)
MYSQL_YYABORT;
spname->init_qname(thd);
@@ -12402,10 +12090,7 @@ drop:
{
LEX *lex=Lex;
if (lex->sphead)
- {
- my_error(ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE"));
lex->set_command(SQLCOM_DROP_PROCEDURE, $3);
lex->spname= $4;
}
@@ -12661,7 +12346,7 @@ ident_eq_value:
;
equal:
- EQ {}
+ '=' {}
| SET_VAR {}
;
@@ -13439,19 +13124,14 @@ opt_extended_describe:
opt_format_json:
/* empty */ {}
- | FORMAT_SYM EQ ident_or_text
+ | FORMAT_SYM '=' ident_or_text
{
if (!my_strcasecmp(system_charset_info, $3.str, "JSON"))
Lex->explain_json= true;
else if (!my_strcasecmp(system_charset_info, $3.str, "TRADITIONAL"))
- {
DBUG_ASSERT(Lex->explain_json==false);
- }
else
- {
- my_error(ER_UNKNOWN_EXPLAIN_FORMAT, MYF(0), $3.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_UNKNOWN_EXPLAIN_FORMAT, MYF(0), $3.str));
}
;
@@ -13548,10 +13228,7 @@ flush_option:
{
LEX *lex= Lex;
if (lex->type & REFRESH_RELAY_LOG)
- {
- my_error(ER_WRONG_USAGE, MYF(0), "FLUSH", "RELAY LOGS");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0), "FLUSH", "RELAY LOGS"));
lex->type|= REFRESH_RELAY_LOG;
lex->relay_log_connection_name= lex->mi.connection_name;
}
@@ -13572,10 +13249,7 @@ flush_option:
{
LEX *lex= Lex;
if (lex->type & REFRESH_SLAVE)
- {
- my_error(ER_WRONG_USAGE, MYF(0), "FLUSH","SLAVE");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0), "FLUSH","SLAVE"));
lex->type|= REFRESH_SLAVE;
lex->reset_slave_info.all= false;
}
@@ -14054,19 +13728,13 @@ param_marker:
Lex_input_stream *lip= YYLIP;
Item_param *item;
if (! lex->parsing_options.allows_variable)
- {
- my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_VIEW_SELECT_VARIABLE, MYF(0)));
const char *query_start= lex->sphead ? lex->sphead->m_tmp_query
: thd->query();
item= new (thd->mem_root) Item_param(thd, lip->get_tok_start() -
query_start);
if (!($$= item) || lex->param_list.push_back(item, thd->mem_root))
- {
- my_message(ER_OUT_OF_RESOURCES, ER_THD(thd, ER_OUT_OF_RESOURCES), MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_OUT_OF_RESOURCES, MYF(0)));
}
;
@@ -14348,10 +14016,7 @@ simple_ident:
{
/* We're compiling a stored procedure and found a variable */
if (! lex->parsing_options.allows_variable)
- {
- my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_VIEW_SELECT_VARIABLE, MYF(0)));
Item_splocal *splocal;
splocal= new (thd->mem_root)
@@ -14427,17 +14092,11 @@ simple_ident_q:
if (lex->trg_chistics.event == TRG_EVENT_INSERT &&
!new_row)
- {
- my_error(ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0), "OLD", "on INSERT");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0), "OLD", "on INSERT"));
if (lex->trg_chistics.event == TRG_EVENT_DELETE &&
new_row)
- {
- my_error(ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0), "NEW", "on DELETE");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0), "NEW", "on DELETE"));
DBUG_ASSERT(!new_row ||
(lex->trg_chistics.event == TRG_EVENT_INSERT ||
@@ -14546,26 +14205,17 @@ field_ident:
{
TABLE_LIST *table= Select->table_list.first;
if (my_strcasecmp(table_alias_charset, $1.str, table->db))
- {
- my_error(ER_WRONG_DB_NAME, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_DB_NAME, MYF(0), $1.str));
if (my_strcasecmp(table_alias_charset, $3.str,
table->table_name))
- {
- my_error(ER_WRONG_TABLE_NAME, MYF(0), $3.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_TABLE_NAME, MYF(0), $3.str));
$$=$5;
}
| ident '.' ident
{
TABLE_LIST *table= Select->table_list.first;
if (my_strcasecmp(table_alias_charset, $1.str, table->alias))
- {
- my_error(ER_WRONG_TABLE_NAME, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_TABLE_NAME, MYF(0), $1.str));
$$=$3;
}
| '.' ident { $$=$2;} /* For Delphi */
@@ -15202,10 +14852,7 @@ set:
{
LEX *lex= Lex;
if (lex->table_or_sp_used())
- {
- my_error(ER_SUBQUERIES_NOT_SUPPORTED, MYF(0), "SET STATEMENT");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0), "SET STATEMENT"));
lex->stmt_var_list= lex->var_list;
lex->var_list.empty();
}
@@ -15534,10 +15181,7 @@ internal_variable_name:
!my_strcasecmp(system_charset_info, $1.str, "OLD")))
{
if ($1.str[0]=='O' || $1.str[0]=='o')
- {
- my_error(ER_TRG_CANT_CHANGE_ROW, MYF(0), "OLD", "");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_TRG_CANT_CHANGE_ROW, MYF(0), "OLD", ""));
if (lex->trg_chistics.event == TRG_EVENT_DELETE)
{
my_error(ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0),
@@ -15545,10 +15189,7 @@ internal_variable_name:
MYSQL_YYABORT;
}
if (lex->trg_chistics.action_time == TRG_ACTION_AFTER)
- {
- my_error(ER_TRG_CANT_CHANGE_ROW, MYF(0), "NEW", "after ");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_TRG_CANT_CHANGE_ROW, MYF(0), "NEW", "after "));
/* This special combination will denote field of NEW row */
$$.var= trg_new_row_fake_var;
$$.base_name= $3;
@@ -15640,10 +15281,7 @@ opt_for_user:
LEX_STRING pw= { C_STRING_WITH_LEN("password") };
if (spc && spc->find_variable(pw, false))
- {
- my_error(ER_SP_BAD_VAR_SHADOW, MYF(0), pw.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BAD_VAR_SHADOW, MYF(0), pw.str));
if (!(lex->definer= (LEX_USER*) thd->calloc(sizeof(LEX_USER))))
MYSQL_YYABORT;
lex->definer->user= current_user;
@@ -15696,10 +15334,7 @@ lock:
LEX *lex= Lex;
if (lex->sphead)
- {
- my_error(ER_SP_BADSTATEMENT, MYF(0), "LOCK");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "LOCK"));
lex->sql_command= SQLCOM_LOCK_TABLES;
}
table_lock_list
@@ -15749,10 +15384,7 @@ unlock:
LEX *lex= Lex;
if (lex->sphead)
- {
- my_error(ER_SP_BADSTATEMENT, MYF(0), "UNLOCK");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "UNLOCK"));
lex->sql_command= SQLCOM_UNLOCK_TABLES;
}
table_or_tables
@@ -15768,34 +15400,25 @@ handler:
{
LEX *lex= Lex;
if (lex->sphead)
- {
- my_error(ER_SP_BADSTATEMENT, MYF(0), "HANDLER");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HANDLER"));
lex->sql_command = SQLCOM_HA_OPEN;
- if (!lex->current_select->add_table_to_list(lex->thd, $2, $4, 0))
+ if (!lex->current_select->add_table_to_list(thd, $2, $4, 0))
MYSQL_YYABORT;
}
| HANDLER_SYM table_ident_nodb CLOSE_SYM
{
LEX *lex= Lex;
if (lex->sphead)
- {
- my_error(ER_SP_BADSTATEMENT, MYF(0), "HANDLER");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HANDLER"));
lex->sql_command = SQLCOM_HA_CLOSE;
- if (!lex->current_select->add_table_to_list(lex->thd, $2, 0, 0))
+ if (!lex->current_select->add_table_to_list(thd, $2, 0, 0))
MYSQL_YYABORT;
}
| HANDLER_SYM table_ident_nodb READ_SYM
{
LEX *lex=Lex;
if (lex->sphead)
- {
- my_error(ER_SP_BADSTATEMENT, MYF(0), "HANDLER");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HANDLER"));
lex->expr_allows_subselect= FALSE;
lex->sql_command = SQLCOM_HA_READ;
lex->ha_rkey_mode= HA_READ_KEY_EXACT; /* Avoid purify warnings */
@@ -15805,7 +15428,7 @@ handler:
lex->current_select->select_limit= one;
lex->current_select->offset_limit= 0;
lex->limit_rows_examined= 0;
- if (!lex->current_select->add_table_to_list(lex->thd, $2, 0, 0))
+ if (!lex->current_select->add_table_to_list(thd, $2, 0, 0))
MYSQL_YYABORT;
}
handler_read_or_scan opt_where_clause opt_limit_clause
@@ -15849,11 +15472,11 @@ handler_rkey_function:
;
handler_rkey_mode:
- EQ { $$=HA_READ_KEY_EXACT; }
+ '=' { $$=HA_READ_KEY_EXACT; }
| GE { $$=HA_READ_KEY_OR_NEXT; }
| LE { $$=HA_READ_KEY_OR_PREV; }
- | GT_SYM { $$=HA_READ_AFTER_KEY; }
- | LT { $$=HA_READ_BEFORE_KEY; }
+ | '>' { $$=HA_READ_AFTER_KEY; }
+ | '<' { $$=HA_READ_BEFORE_KEY; }
;
/* GRANT / REVOKE */
@@ -16011,10 +15634,7 @@ grant_role:
/* 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), "");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_INVALID_ROLE, MYF(0), ""));
if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
MYSQL_YYABORT;
$$->user = $1;
@@ -16109,30 +15729,21 @@ require_list_element:
{
LEX *lex=Lex;
if (lex->x509_subject)
- {
- my_error(ER_DUP_ARGUMENT, MYF(0), "SUBJECT");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "SUBJECT"));
lex->x509_subject=$2.str;
}
| ISSUER_SYM TEXT_STRING
{
LEX *lex=Lex;
if (lex->x509_issuer)
- {
- my_error(ER_DUP_ARGUMENT, MYF(0), "ISSUER");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "ISSUER"));
lex->x509_issuer=$2.str;
}
| CIPHER_SYM TEXT_STRING
{
LEX *lex=Lex;
if (lex->ssl_cipher)
- {
- my_error(ER_DUP_ARGUMENT, MYF(0), "CIPHER");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "CIPHER"));
lex->ssl_cipher=$2.str;
}
;
@@ -16147,11 +15758,7 @@ grant_ident:
if (lex->grant == GLOBAL_ACLS)
lex->grant = DB_ACLS & ~GRANT_ACL;
else if (lex->columns.elements)
- {
- my_message(ER_ILLEGAL_GRANT_FOR_TABLE,
- ER_THD(thd, ER_ILLEGAL_GRANT_FOR_TABLE), MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_ILLEGAL_GRANT_FOR_TABLE, MYF(0)));
}
| ident '.' '*'
{
@@ -16160,11 +15767,7 @@ grant_ident:
if (lex->grant == GLOBAL_ACLS)
lex->grant = DB_ACLS & ~GRANT_ACL;
else if (lex->columns.elements)
- {
- my_message(ER_ILLEGAL_GRANT_FOR_TABLE,
- ER_THD(thd, ER_ILLEGAL_GRANT_FOR_TABLE), MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_ILLEGAL_GRANT_FOR_TABLE, MYF(0)));
}
| '*' '.' '*'
{
@@ -16173,16 +15776,12 @@ grant_ident:
if (lex->grant == GLOBAL_ACLS)
lex->grant= GLOBAL_ACLS & ~GRANT_ACL;
else if (lex->columns.elements)
- {
- my_message(ER_ILLEGAL_GRANT_FOR_TABLE,
- ER_THD(thd, ER_ILLEGAL_GRANT_FOR_TABLE), MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_ILLEGAL_GRANT_FOR_TABLE, MYF(0)));
}
| table_ident
{
LEX *lex=Lex;
- if (!lex->current_select->add_table_to_list(lex->thd, $1,NULL,
+ if (!lex->current_select->add_table_to_list(thd, $1,NULL,
TL_OPTION_UPDATING))
MYSQL_YYABORT;
if (lex->grant == GLOBAL_ACLS)
@@ -16749,7 +16348,7 @@ no_definer:
;
definer:
- DEFINER_SYM EQ user_or_role
+ DEFINER_SYM '=' user_or_role
{
Lex->definer= $3;
Lex->ssl_type= SSL_TYPE_NOT_SPECIFIED;
@@ -16765,11 +16364,11 @@ definer:
**************************************************************************/
view_algorithm:
- ALGORITHM_SYM EQ UNDEFINED_SYM
+ ALGORITHM_SYM '=' UNDEFINED_SYM
{ Lex->create_view_algorithm= DTYPE_ALGORITHM_UNDEFINED; }
- | ALGORITHM_SYM EQ MERGE_SYM
+ | ALGORITHM_SYM '=' MERGE_SYM
{ Lex->create_view_algorithm= VIEW_ALGORITHM_MERGE; }
- | ALGORITHM_SYM EQ TEMPTABLE_SYM
+ | ALGORITHM_SYM '=' TEMPTABLE_SYM
{ Lex->create_view_algorithm= VIEW_ALGORITHM_TMPTABLE; }
;
@@ -16897,10 +16496,7 @@ trigger_tail:
Lex_input_stream *lip= YYLIP;
if (lex->sphead)
- {
- my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "TRIGGER");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_NO_RECURSIVE_CREATE, MYF(0), "TRIGGER"));
lex->stmt_definition_begin= $2;
lex->ident.str= $9;
@@ -16957,10 +16553,7 @@ udf_tail2:
if (lex->add_create_options_with_check($2))
MYSQL_YYABORT;
if (is_native_function(thd, & $3))
- {
- my_error(ER_NATIVE_FCT_NAME_COLLISION, MYF(0), $3.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_NATIVE_FCT_NAME_COLLISION, MYF(0), $3.str));
lex->sql_command= SQLCOM_CREATE_FUNCTION;
lex->udf.name= $3;
lex->udf.returns= (Item_result) $5;
@@ -16983,10 +16576,7 @@ sf_tail:
lex->spname= $3;
if (lex->sphead)
- {
- my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "FUNCTION");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_NO_RECURSIVE_CREATE, MYF(0), "FUNCTION"));
if (!make_sp_head(thd, $3, TYPE_ENUM_FUNCTION))
MYSQL_YYABORT;
@@ -17029,10 +16619,7 @@ sf_tail:
lex->sql_command= SQLCOM_CREATE_SPFUNCTION;
sp->set_stmt_end(thd);
if (!(sp->m_flags & sp_head::HAS_RETURN))
- {
- my_error(ER_SP_NORETURN, MYF(0), sp->m_qname.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_NORETURN, MYF(0), sp->m_qname.str));
if (is_native_function(thd, & sp->m_name))
{
/*
@@ -17079,10 +16666,7 @@ sp_tail:
MYSQL_YYABORT;
if (Lex->sphead)
- {
- my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "PROCEDURE");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_NO_RECURSIVE_CREATE, MYF(0), "PROCEDURE"));
if (!make_sp_head(thd, $3, TYPE_ENUM_PROCEDURE))
MYSQL_YYABORT;
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 79743dbfc13..db054a635af 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -2383,7 +2383,9 @@ export const char *optimizer_switch_names[]=
"table_elimination",
"extended_keys",
"exists_to_in",
- "default", NullS
+ "orderby_uses_equalities",
+ "default",
+ NullS
};
static bool fix_optimizer_switch(sys_var *self, THD *thd,
enum_var_type type)
@@ -4725,7 +4727,7 @@ static Sys_var_charptr Sys_wsrep_cluster_address (
static Sys_var_charptr Sys_wsrep_node_name (
"wsrep_node_name", "Node name",
PREALLOCATED GLOBAL_VAR(wsrep_node_name), CMD_LINE(REQUIRED_ARG),
- IN_SYSTEM_CHARSET, DEFAULT(""), NO_MUTEX_GUARD, NOT_IN_BINLOG,
+ IN_SYSTEM_CHARSET, DEFAULT(glob_hostname), NO_MUTEX_GUARD, NOT_IN_BINLOG,
wsrep_node_name_check, wsrep_node_name_update);
static Sys_var_charptr Sys_wsrep_node_address (
@@ -4867,7 +4869,8 @@ static bool fix_wsrep_causal_reads(sys_var *self, THD* thd, enum_var_type var_ty
static Sys_var_mybool Sys_wsrep_causal_reads(
"wsrep_causal_reads", "Setting this variable is equivalent "
"to setting wsrep_sync_wait READ flag",
- SESSION_VAR(wsrep_causal_reads), CMD_LINE(OPT_ARG), DEFAULT(FALSE),
+ SESSION_VAR(wsrep_causal_reads),
+ CMD_LINE(OPT_ARG, OPT_WSREP_CAUSAL_READS), DEFAULT(FALSE),
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
ON_UPDATE(fix_wsrep_causal_reads),
DEPRECATED("'@@wsrep_sync_wait=1'"));
@@ -4877,7 +4880,7 @@ static Sys_var_uint Sys_wsrep_sync_wait(
"an operation of the type specified by bitmask: 1 - READ(includes "
"SELECT, SHOW and BEGIN/START TRANSACTION); 2 - UPDATE and DELETE; 4 - "
"INSERT and REPLACE",
- SESSION_VAR(wsrep_sync_wait), CMD_LINE(OPT_ARG),
+ SESSION_VAR(wsrep_sync_wait), CMD_LINE(OPT_ARG, OPT_WSREP_SYNC_WAIT),
VALID_RANGE(WSREP_SYNC_WAIT_NONE, WSREP_SYNC_WAIT_MAX),
DEFAULT(WSREP_SYNC_WAIT_NONE), BLOCK_SIZE(1),
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
diff --git a/sql/sys_vars.ic b/sql/sys_vars.ic
index 2488e804310..ca6634849a1 100644
--- a/sql/sys_vars.ic
+++ b/sql/sys_vars.ic
@@ -30,6 +30,7 @@
#include "strfunc.h"
#include "tztime.h" // my_tz_find, my_tz_SYSTEM, struct Time_zone
#include "rpl_mi.h" // For Multi-Source Replication
+#include "debug_sync.h"
/*
a set of mostly trivial (as in f(X)=X) defines below to make system variable
diff --git a/sql/table.cc b/sql/table.cc
index cee16cd9e77..d4adb5ca356 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -3755,18 +3755,23 @@ bool get_field(MEM_ROOT *mem, Field *field, String *res)
{
char buff[MAX_FIELD_WIDTH], *to;
String str(buff,sizeof(buff),&my_charset_bin);
- uint length;
+ bool rc;
+ THD *thd= field->get_thd();
+ ulonglong sql_mode_backup= thd->variables.sql_mode;
+ thd->variables.sql_mode&= ~MODE_PAD_CHAR_TO_FULL_LENGTH;
field->val_str(&str);
- if (!(length= str.length()))
+ if ((rc= !str.length() ||
+ !(to= strmake_root(mem, str.ptr(), str.length()))))
{
res->length(0);
- return 1;
+ goto ex;
}
- if (!(to= strmake_root(mem, str.ptr(), length)))
- length= 0; // Safety fix
- res->set(to, length, field->charset());
- return 0;
+ res->set(to, str.length(), field->charset());
+
+ex:
+ thd->variables.sql_mode= sql_mode_backup;
+ return rc;
}
@@ -3785,17 +3790,10 @@ bool get_field(MEM_ROOT *mem, Field *field, String *res)
char *get_field(MEM_ROOT *mem, Field *field)
{
- char buff[MAX_FIELD_WIDTH], *to;
- String str(buff,sizeof(buff),&my_charset_bin);
- uint length;
-
- field->val_str(&str);
- length= str.length();
- if (!length || !(to= (char*) alloc_root(mem,length+1)))
- return NullS;
- memcpy(to,str.ptr(),(uint) length);
- to[length]=0;
- return to;
+ String str;
+ bool rc= get_field(mem, field, &str);
+ DBUG_ASSERT(rc || str.ptr()[str.length()] == '\0');
+ return rc ? NullS : (char *) str.ptr();
}
/*
diff --git a/sql/threadpool_unix.cc b/sql/threadpool_unix.cc
index 91b392eb766..4079091e217 100644
--- a/sql/threadpool_unix.cc
+++ b/sql/threadpool_unix.cc
@@ -170,6 +170,7 @@ struct pool_timer_t
volatile uint64 next_timeout_check;
int tick_interval;
bool shutdown;
+ pthread_t timer_thread_id;
};
static pool_timer_t pool_timer;
@@ -607,12 +608,12 @@ void check_stall(thread_group_t *thread_group)
static void start_timer(pool_timer_t* timer)
{
- pthread_t thread_id;
DBUG_ENTER("start_timer");
mysql_mutex_init(key_timer_mutex,&timer->mutex, NULL);
mysql_cond_init(key_timer_cond, &timer->cond, NULL);
timer->shutdown = false;
- mysql_thread_create(key_timer_thread,&thread_id, NULL, timer_thread, timer);
+ mysql_thread_create(key_timer_thread, &timer->timer_thread_id, NULL,
+ timer_thread, timer);
DBUG_VOID_RETURN;
}
@@ -624,6 +625,7 @@ static void stop_timer(pool_timer_t *timer)
timer->shutdown = true;
mysql_cond_signal(&timer->cond);
mysql_mutex_unlock(&timer->mutex);
+ pthread_join(timer->timer_thread_id, NULL);
DBUG_VOID_RETURN;
}
diff --git a/sql/winservice.c b/sql/winservice.c
index 1cf9f8d7823..74e9e56acc6 100644
--- a/sql/winservice.c
+++ b/sql/winservice.c
@@ -81,8 +81,10 @@ void normalize_path(char *path, size_t size)
and services. We do not want to mess up with these installations. We will
just ignore such services, pretending it is not MySQL.
- ´@return
- TRUE, if this service should be excluded from UI lists etc (OEM install)
+ We also exclude MySQL5.7+ since we cannot upgrade it (and it is not an upgrade anyway)
+
+ @return
+ TRUE, if this service should be excluded from UI lists etc
FALSE otherwise.
*/
BOOL exclude_service(mysqld_service_properties *props)
@@ -104,7 +106,12 @@ BOOL exclude_service(mysqld_service_properties *props)
if (strstr(buf, exclude_patterns[i]))
return TRUE;
}
-
+ if ((props->version_major == 0) ||
+ (props->version_major > 5 && props->version_major < 10) ||
+ (props->version_major == 5 && props->version_minor > 6))
+ {
+ return TRUE;
+ }
return FALSE;
}
diff --git a/sql/wsrep_applier.h b/sql/wsrep_applier.h
index b6497776e87..d58d3cdc54e 100644
--- a/sql/wsrep_applier.h
+++ b/sql/wsrep_applier.h
@@ -23,6 +23,7 @@ void wsrep_set_apply_format(THD* thd, Format_description_log_event* ev);
Format_description_log_event* wsrep_get_apply_format(THD* thd);
/* wsrep callback prototypes */
+extern "C" {
wsrep_cb_status_t wsrep_apply_cb(void *ctx,
const void* buf, size_t buf_len,
@@ -39,4 +40,5 @@ wsrep_cb_status_t wsrep_unordered_cb(void* ctx,
const void* data,
size_t size);
+} /* extern "C" */
#endif /* WSREP_APPLIER_H */
diff --git a/sql/wsrep_binlog.h b/sql/wsrep_binlog.h
index d8a2eb51d4a..1e820529211 100644
--- a/sql/wsrep_binlog.h
+++ b/sql/wsrep_binlog.h
@@ -38,10 +38,10 @@ int wsrep_write_cache_buf(IO_CACHE *cache, uchar **buf, size_t *buf_len);
@param len total amount of data written
@return wsrep error status
*/
-int wsrep_write_cache (wsrep_t* wsrep,
- THD* thd,
- IO_CACHE* cache,
- size_t* len);
+int wsrep_write_cache (wsrep_t* const wsrep,
+ THD* const thd,
+ IO_CACHE* const cache,
+ size_t* const len);
/* Dump replication buffer to disk */
void wsrep_dump_rbr_buf(THD *thd, const void* rbr_buf, size_t buf_len);
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc
index 9f7c3c9baa7..e3b503a82fb 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -564,8 +564,6 @@ int wsrep_init()
wsrep_sst_auth_init(wsrep_sst_auth);
- wsrep_causal_reads_update(&global_system_variables);
-
wsrep_ready_set(FALSE);
assert(wsrep_provider);
@@ -891,6 +889,9 @@ bool wsrep_start_replication()
{
wsrep_status_t rcode;
+ /* wsrep provider must be loaded. */
+ DBUG_ASSERT(wsrep);
+
/*
if provider is trivial, don't even try to connect,
but resume local node operation
@@ -1268,7 +1269,7 @@ wsrep_alter_query_string(THD *thd, String *buf)
return 0;
}
-int wsrep_alter_event_query(THD *thd, uchar** buf, size_t* buf_len)
+static int wsrep_alter_event_query(THD *thd, uchar** buf, size_t* buf_len)
{
String log_query;
@@ -1364,6 +1365,10 @@ create_view_query(THD *thd, uchar** buf, size_t* buf_len)
return wsrep_to_buf_helper(thd, buff.ptr(), buff.length(), buf, buf_len);
}
+/* Forward declarations. */
+static int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len);
+static int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len);
+
/*
returns:
0: statement was replicated as TOI
@@ -2173,7 +2178,7 @@ void wsrep_kill_mysql(THD *thd)
}
-int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len)
+static int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len)
{
String log_query;
sp_head *sp = thd->lex->sphead;
@@ -2487,7 +2492,7 @@ error:
}
-int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len)
+static int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len)
{
LEX *lex= thd->lex;
String stmt_query;
diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h
index e91ed2302a2..ea81384da75 100644
--- a/sql/wsrep_mysqld.h
+++ b/sql/wsrep_mysqld.h
@@ -280,10 +280,7 @@ void wsrep_to_isolation_end(THD *thd);
void wsrep_cleanup_transaction(THD *thd);
int wsrep_to_buf_helper(
THD* thd, const char *query, uint query_len, uchar** buf, size_t* buf_len);
-int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len);
-int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len);
int wsrep_create_event_query(THD *thd, uchar** buf, size_t* buf_len);
-int wsrep_alter_event_query(THD *thd, uchar** buf, size_t* buf_len);
extern bool
wsrep_grant_mdl_exception(MDL_context *requestor_ctx,
@@ -304,14 +301,12 @@ void wsrep_close_applier_threads(int count);
void wsrep_wait_appliers_close(THD *thd);
void wsrep_kill_mysql(THD *thd);
void wsrep_close_threads(THD *thd);
-int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len);
void wsrep_copy_query(THD *thd);
bool wsrep_is_show_query(enum enum_sql_command command);
void wsrep_replay_transaction(THD *thd);
bool wsrep_create_like_table(THD* thd, TABLE_LIST* table,
TABLE_LIST* src_table,
HA_CREATE_INFO *create_info);
-int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len);
#else /* WITH_WSREP */
diff --git a/sql/wsrep_priv.h b/sql/wsrep_priv.h
index a6e57e33e6d..e2dc526608f 100644
--- a/sql/wsrep_priv.h
+++ b/sql/wsrep_priv.h
@@ -40,8 +40,12 @@ extern wsrep_uuid_t local_uuid;
extern wsrep_seqno_t local_seqno;
// a helper function
-bool wsrep_sst_received(wsrep_t*, const wsrep_uuid_t&, wsrep_seqno_t,
- const void*, size_t, bool const);
+bool wsrep_sst_received (wsrep_t* const wsrep,
+ const wsrep_uuid_t& uuid,
+ const wsrep_seqno_t seqno,
+ const void* const state,
+ const size_t state_len,
+ const bool implicit);
/*! SST thread signals init thread about sst completion */
void wsrep_sst_complete(const wsrep_uuid_t*, wsrep_seqno_t, bool);
diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc
index 4fb162f9995..6d0cfc1c43a 100644
--- a/sql/wsrep_sst.cc
+++ b/sql/wsrep_sst.cc
@@ -398,6 +398,7 @@ static int sst_scan_uuid_seqno (const char* str,
wsrep_uuid_t* uuid, wsrep_seqno_t* seqno)
{
int offt = wsrep_uuid_scan (str, strlen(str), uuid);
+ errno= 0; /* Reset the errno */
if (offt > 0 && strlen(str) > (unsigned int)offt && ':' == str[offt])
{
*seqno = strtoll (str + offt + 1, NULL, 10);
diff --git a/sql/wsrep_utils.h b/sql/wsrep_utils.h
index 54235cf5273..e4f421930f4 100644
--- a/sql/wsrep_utils.h
+++ b/sql/wsrep_utils.h
@@ -19,7 +19,7 @@
#include "wsrep_priv.h"
#include "wsrep_mysqld.h"
-unsigned int wsrep_check_ip (const char* addr, bool *is_ipv6);
+unsigned int wsrep_check_ip (const char* const addr, bool *is_ipv6);
size_t wsrep_guess_ip (char* buf, size_t buf_len);
namespace wsp {
@@ -155,6 +155,7 @@ private:
}
bool parse_port(const char *port) {
+ errno= 0; /* Reset the errno */
m_port= strtol(port, NULL, 10);
if (errno == EINVAL || errno == ERANGE)
{
diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc
index 1407f715fb4..8e443b573cb 100644
--- a/sql/wsrep_var.cc
+++ b/sql/wsrep_var.cc
@@ -384,7 +384,16 @@ bool wsrep_cluster_address_check (sys_var *self, THD* thd, set_var* var)
bool wsrep_cluster_address_update (sys_var *self, THD* thd, enum_var_type type)
{
- bool wsrep_on_saved= thd->variables.wsrep_on;
+ bool wsrep_on_saved;
+
+ /* Do not proceed if wsrep provider is not loaded. */
+ if (!wsrep)
+ {
+ WSREP_INFO("wsrep provider is not loaded, can't re(start) replication.");
+ return false;
+ }
+
+ wsrep_on_saved= thd->variables.wsrep_on;
thd->variables.wsrep_on= false;
/* stop replication is heavy operation, and includes closing all client