summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2017-06-19 17:28:08 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2017-06-19 17:28:08 +0300
commit1e3886ae80c44a39ec3e4061b4ea3131cdcef213 (patch)
treece95518792d1432b669ba13a248928e74e81a9bb /sql
parent0fe7d8a2a221196d977e5efe3f3dedb22806bb53 (diff)
parent3a7201ea922f6d3373924c413fdb4b108f6208c5 (diff)
downloadmariadb-git-1e3886ae80c44a39ec3e4061b4ea3131cdcef213.tar.gz
Merge bb-10.2-ext into 10.3
Diffstat (limited to 'sql')
-rw-r--r--sql/CMakeLists.txt15
-rw-r--r--sql/discover.cc3
-rw-r--r--sql/events.cc2
-rw-r--r--sql/filesort.cc7
-rw-r--r--sql/ha_sequence.cc14
-rw-r--r--sql/handler.cc54
-rw-r--r--sql/handler.h4
-rw-r--r--sql/item.cc6
-rw-r--r--sql/item.h4
-rw-r--r--sql/item_cmpfunc.cc83
-rw-r--r--sql/item_cmpfunc.h14
-rw-r--r--sql/item_func.cc5
-rw-r--r--sql/item_func.h31
-rw-r--r--sql/item_strfunc.cc12
-rw-r--r--sql/item_subselect.cc29
-rw-r--r--sql/item_subselect.h8
-rw-r--r--sql/item_sum.h1
-rw-r--r--sql/item_windowfunc.cc2
-rw-r--r--sql/lock.cc3
-rw-r--r--sql/log.cc9
-rw-r--r--sql/log_event.cc1
-rw-r--r--sql/log_event_old.cc2
-rw-r--r--sql/mysqld.cc16
-rw-r--r--sql/mysqld.h4
-rw-r--r--sql/opt_range.cc9
-rw-r--r--sql/opt_subselect.cc109
-rw-r--r--sql/opt_sum.cc12
-rw-r--r--sql/rpl_gtid.cc2
-rw-r--r--sql/rpl_mi.cc57
-rw-r--r--sql/rpl_mi.h2
-rw-r--r--sql/share/errmsg-utf8.txt2
-rw-r--r--sql/slave.cc5
-rw-r--r--sql/sp_head.cc2
-rw-r--r--sql/sql_acl.cc6
-rw-r--r--sql/sql_audit.cc9
-rw-r--r--sql/sql_cache.cc8
-rw-r--r--sql/sql_class.cc15
-rw-r--r--sql/sql_class.h2
-rw-r--r--sql/sql_digest.cc4
-rw-r--r--sql/sql_insert.cc15
-rw-r--r--sql/sql_lex.cc6
-rw-r--r--sql/sql_lex.h6
-rw-r--r--sql/sql_parse.cc23
-rw-r--r--sql/sql_plugin.cc5
-rw-r--r--sql/sql_prepare.cc228
-rw-r--r--sql/sql_prepare.h3
-rw-r--r--sql/sql_reload.cc11
-rw-r--r--sql/sql_repl.cc6
-rw-r--r--sql/sql_select.cc60
-rw-r--r--sql/sql_sequence.cc26
-rw-r--r--sql/sql_sequence.h4
-rw-r--r--sql/sql_show.cc13
-rw-r--r--sql/sql_table.cc11
-rw-r--r--sql/sql_yacc.yy31
-rw-r--r--sql/sql_yacc_ora.yy29
-rw-r--r--sql/sys_vars.cc3
-rw-r--r--sql/table.cc39
-rw-r--r--sql/wsrep_thd.cc3
58 files changed, 775 insertions, 320 deletions
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt
index 87e41817857..88a4e40e373 100644
--- a/sql/CMakeLists.txt
+++ b/sql/CMakeLists.txt
@@ -62,15 +62,22 @@ SET_SOURCE_FILES_PROPERTIES(${GEN_SOURCES}
# Gen_lex_token
# Make sure sql_yacc.h is generated before compiling gen_lex_token
+
+IF(NOT CMAKE_GENERATOR MATCHES "Visual Studio")
+ SET(DEPENDS_gen_lex_token DEPENDS gen_lex_token)
+ SET(DEPENDS_gen_lex_hash DEPENDS gen_lex_hash)
+ENDIF()
+
+
IF(NOT CMAKE_CROSSCOMPILING)
- ADD_EXECUTABLE(gen_lex_token gen_lex_token.cc)
- ADD_DEPENDENCIES(gen_lex_token GenServerSource)
+ ADD_EXECUTABLE(gen_lex_token gen_lex_token.cc
+ ${CMAKE_CURRENT_BINARY_DIR}/sql_yacc.h)
ENDIF()
ADD_CUSTOM_COMMAND(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/lex_token.h
COMMAND gen_lex_token > lex_token.h
- DEPENDS gen_lex_token
+ ${DEPENDS_gen_lex_token}
)
ADD_DEFINITIONS(-DMYSQL_SERVER -DHAVE_EVENT_SCHEDULER)
@@ -341,7 +348,7 @@ ENDIF()
ADD_CUSTOM_COMMAND(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/lex_hash.h
COMMAND gen_lex_hash > lex_hash.h
- DEPENDS gen_lex_hash
+ ${DEPENDS_gen_lex_hash}
)
MYSQL_ADD_EXECUTABLE(mysql_tzinfo_to_sql tztime.cc COMPONENT Server)
diff --git a/sql/discover.cc b/sql/discover.cc
index d8ed718fc58..d8bf6ca79c5 100644
--- a/sql/discover.cc
+++ b/sql/discover.cc
@@ -89,8 +89,7 @@ int readfrm(const char *name, const uchar **frmdata, size_t *len)
error= 0;
err:
- if (file > 0)
- (void) mysql_file_close(file, MYF(MY_WME));
+ (void) mysql_file_close(file, MYF(MY_WME));
err_end: /* Here when no file */
DBUG_RETURN (error);
diff --git a/sql/events.cc b/sql/events.cc
index 978a1ebc710..86e85d7f757 100644
--- a/sql/events.cc
+++ b/sql/events.cc
@@ -1,5 +1,6 @@
/*
Copyright (c) 2005, 2013, Oracle and/or its affiliates.
+ Copyright (c) 2017, MariaDB Corporation.
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
@@ -243,6 +244,7 @@ common_1_lev_code:
break;
case INTERVAL_WEEK:
expr/= 7;
+ /* fall through */
default:
close_quote= FALSE;
break;
diff --git a/sql/filesort.cc b/sql/filesort.cc
index 007216b392f..8ca6cd04cda 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -182,12 +182,6 @@ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort,
outfile= &sort->io_cache;
- /*
- Release InnoDB's adaptive hash index latch (if holding) before
- running a sort.
- */
- ha_release_temporary_latches(thd);
-
my_b_clear(&tempfile);
my_b_clear(&buffpek_pointers);
buffpek=0;
@@ -953,6 +947,7 @@ write_keys(Sort_param *param, SORT_INFO *fs_info, uint count,
/* check we won't have more buffpeks than we can possibly keep in memory */
if (my_b_tell(buffpek_pointers) + sizeof(BUFFPEK) > (ulonglong)UINT_MAX)
goto err;
+ bzero(&buffpek, sizeof(buffpek));
buffpek.file_pos= my_b_tell(tempfile);
if ((ha_rows) count > param->max_rows)
count=(uint) param->max_rows; /* purecov: inspected */
diff --git a/sql/ha_sequence.cc b/sql/ha_sequence.cc
index e0e9e2a42e7..7f2248bf3cb 100644
--- a/sql/ha_sequence.cc
+++ b/sql/ha_sequence.cc
@@ -198,6 +198,18 @@ int ha_sequence::write_row(uchar *buf)
/* This calls is from ha_open() as part of create table */
DBUG_RETURN(file->write_row(buf));
}
+ if (unlikely(sequence->initialized == SEQUENCE::SEQ_IN_ALTER))
+ {
+ int error= 0;
+ /* This is called from alter table */
+ tmp_seq.read_fields(table);
+ if (tmp_seq.check_and_adjust(0))
+ DBUG_RETURN(HA_ERR_SEQUENCE_INVALID_DATA);
+ sequence->copy(&tmp_seq);
+ if (!(error= file->write_row(buf)))
+ sequence->initialized= SEQUENCE::SEQ_READY_TO_USE;
+ DBUG_RETURN(error);
+ }
if (unlikely(sequence->initialized != SEQUENCE::SEQ_READY_TO_USE))
DBUG_RETURN(HA_ERR_WRONG_COMMAND);
@@ -280,7 +292,7 @@ int ha_sequence::extra(enum ha_extra_function operation)
if (operation == HA_EXTRA_PREPARE_FOR_ALTER_TABLE)
{
/* In case of ALTER TABLE allow ::write_row() to copy rows */
- sequence->initialized= SEQUENCE::SEQ_IN_PREPARE;
+ sequence->initialized= SEQUENCE::SEQ_IN_ALTER;
}
return file->extra(operation);
}
diff --git a/sql/handler.cc b/sql/handler.cc
index 9b66801b109..c74675ed113 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -2020,44 +2020,6 @@ commit_checkpoint_notify_ha(handlerton *hton, void *cookie)
/**
- @details
- This function should be called when MySQL sends rows of a SELECT result set
- or the EOF mark to the client. It releases a possible adaptive hash index
- S-latch held by thd in InnoDB and also releases a possible InnoDB query
- FIFO ticket to enter InnoDB. To save CPU time, InnoDB allows a thd to
- keep them over several calls of the InnoDB handler interface when a join
- is executed. But when we let the control to pass to the client they have
- to be released because if the application program uses mysql_use_result(),
- it may deadlock on the S-latch if the application on another connection
- performs another SQL query. In MySQL-4.1 this is even more important because
- there a connection can have several SELECT queries open at the same time.
-
- @param thd the thread handle of the current connection
-
- @return
- always 0
-*/
-
-int ha_release_temporary_latches(THD *thd)
-{
- Ha_trx_info *info;
-
- /*
- Note that below we assume that only transactional storage engines
- may need release_temporary_latches(). If this will ever become false,
- we could iterate on thd->open_tables instead (and remove duplicates
- as if (!seen[hton->slot]) { seen[hton->slot]=1; ... }).
- */
- for (info= thd->transaction.stmt.ha_list; info; info= info->next())
- {
- handlerton *hton= info->ht();
- if (hton && hton->release_temporary_latches)
- hton->release_temporary_latches(hton, thd);
- }
- return 0;
-}
-
-/**
Check if all storage engines used in transaction agree that after
rollback to savepoint it is safe to release MDL locks acquired after
savepoint creation.
@@ -5685,6 +5647,20 @@ bool handler::check_table_binlog_row_based_internal(bool binlog_row)
table->file->partition_ht()->db_type != DB_TYPE_INNODB) ||
(thd->wsrep_ignore_table == true)))
return 0;
+
+ /* enforce wsrep_max_ws_rows */
+ if (WSREP(thd) && table->s->tmp_table == NO_TMP_TABLE)
+ {
+ thd->wsrep_affected_rows++;
+ if (wsrep_max_ws_rows &&
+ thd->wsrep_exec_mode != REPL_RECV &&
+ thd->wsrep_affected_rows > wsrep_max_ws_rows)
+ {
+ trans_rollback_stmt(thd) || trans_rollback(thd);
+ my_message(ER_ERROR_DURING_COMMIT, "wsrep_max_ws_rows exceeded", MYF(0));
+ return ER_ERROR_DURING_COMMIT;
+ }
+ }
#endif
return (table->s->cached_row_logging_check &&
@@ -5893,7 +5869,7 @@ int handler::ha_external_lock(THD *thd, int lock_type)
DBUG_EXECUTE_IF("external_lock_failure", error= HA_ERR_GENERIC;);
- if (error == 0)
+ if (error == 0 || lock_type == F_UNLCK)
{
m_lock_type= lock_type;
cached_table_flags= table_flags();
diff --git a/sql/handler.h b/sql/handler.h
index 98269118bea..52e7f276db0 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -1235,7 +1235,6 @@ struct handlerton
enum_binlog_command binlog_command,
const char *query, uint query_length,
const char *db, const char *table_name);
- int (*release_temporary_latches)(handlerton *hton, THD *thd);
/*
Get log status.
@@ -4362,9 +4361,6 @@ int ha_change_key_cache_param(KEY_CACHE *key_cache);
int ha_repartition_key_cache(KEY_CACHE *key_cache);
int ha_change_key_cache(KEY_CACHE *old_key_cache, KEY_CACHE *new_key_cache);
-/* report to InnoDB that control passes to the client */
-int ha_release_temporary_latches(THD *thd);
-
/* transactions: interface to handlerton functions */
int ha_start_consistent_snapshot(THD *thd);
int ha_commit_or_rollback_by_xid(XID *xid, bool commit);
diff --git a/sql/item.cc b/sql/item.cc
index f4236eee013..173444ad580 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2016, Oracle and/or its affiliates.
- Copyright (c) 2010, 2016, MariaDB
+ Copyright (c) 2010, 2017, 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
@@ -3635,7 +3635,7 @@ Item_param::Item_param(THD *thd, const LEX_CSTRING *name_arg,
state(NO_VALUE),
/* Don't pretend to be a literal unless value for this item is set. */
item_type(PARAM_ITEM),
- indicators(0), indicator(STMT_INDICATOR_NONE),
+ indicator(STMT_INDICATOR_NONE),
set_param_func(default_set_param_func),
m_out_param_info(NULL),
/*
@@ -5763,7 +5763,7 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
SELECT_LEX *select= thd->lex->current_select;
thd->change_item_tree(reference,
- select->parsing_place == IN_GROUP_BY &&
+ select->context_analysis_place == IN_GROUP_BY &&
alias_name_used ? *rf->ref : rf);
/*
diff --git a/sql/item.h b/sql/item.h
index 76ce4aa935f..bc349e8003a 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -3066,10 +3066,8 @@ public:
};
/*
- Used for bulk protocol. Indicates if we should expect
- indicators byte before value of the parameter
+ Used for bulk protocol only.
*/
- my_bool indicators;
enum enum_indicator_type indicator;
/*
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 07b5f90bf69..49135e846cd 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -5264,6 +5264,15 @@ int Regexp_processor_pcre::default_regex_flags()
return default_regex_flags_pcre(current_thd);
}
+void Regexp_processor_pcre::set_recursion_limit(THD *thd)
+{
+ long stack_used;
+ DBUG_ASSERT(thd == current_thd);
+ stack_used= available_stack_size(thd->thread_stack, &stack_used);
+ m_pcre_extra.match_limit_recursion=
+ (my_thread_stack_size - stack_used)/my_pcre_frame_size;
+}
+
/**
Convert string to lib_charset, if needed.
@@ -5355,15 +5364,77 @@ void Regexp_processor_pcre::pcre_exec_warn(int rc) const
*/
switch (rc)
{
+ case PCRE_ERROR_NULL:
+ errmsg= "pcre_exec: null arguement passed";
+ break;
+ case PCRE_ERROR_BADOPTION:
+ errmsg= "pcre_exec: bad option";
+ break;
+ case PCRE_ERROR_BADMAGIC:
+ errmsg= "pcre_exec: bad magic - not a compiled regex";
+ break;
+ case PCRE_ERROR_UNKNOWN_OPCODE:
+ errmsg= "pcre_exec: error in compiled regex";
+ break;
case PCRE_ERROR_NOMEMORY:
errmsg= "pcre_exec: Out of memory";
break;
+ case PCRE_ERROR_NOSUBSTRING:
+ errmsg= "pcre_exec: no substring";
+ break;
+ case PCRE_ERROR_MATCHLIMIT:
+ errmsg= "pcre_exec: match limit exceeded";
+ break;
+ case PCRE_ERROR_CALLOUT:
+ errmsg= "pcre_exec: callout error";
+ break;
case PCRE_ERROR_BADUTF8:
errmsg= "pcre_exec: Invalid utf8 byte sequence in the subject string";
break;
+ case PCRE_ERROR_BADUTF8_OFFSET:
+ errmsg= "pcre_exec: Started at invalid location within utf8 byte sequence";
+ break;
+ case PCRE_ERROR_PARTIAL:
+ errmsg= "pcre_exec: partial match";
+ break;
+ case PCRE_ERROR_INTERNAL:
+ errmsg= "pcre_exec: internal error";
+ break;
+ case PCRE_ERROR_BADCOUNT:
+ errmsg= "pcre_exec: ovesize is negative";
+ break;
+ case PCRE_ERROR_RECURSIONLIMIT:
+ my_snprintf(buf, sizeof(buf), "pcre_exec: recursion limit of %ld exceeded",
+ m_pcre_extra.match_limit_recursion);
+ errmsg= buf;
+ break;
+ case PCRE_ERROR_BADNEWLINE:
+ errmsg= "pcre_exec: bad newline options";
+ break;
+ case PCRE_ERROR_BADOFFSET:
+ errmsg= "pcre_exec: start offset negative or greater than string length";
+ break;
+ case PCRE_ERROR_SHORTUTF8:
+ errmsg= "pcre_exec: ended in middle of utf8 sequence";
+ break;
+ case PCRE_ERROR_JIT_STACKLIMIT:
+ errmsg= "pcre_exec: insufficient stack memory for JIT compile";
+ break;
case PCRE_ERROR_RECURSELOOP:
errmsg= "pcre_exec: Recursion loop detected";
break;
+ case PCRE_ERROR_BADMODE:
+ errmsg= "pcre_exec: compiled pattern passed to wrong bit library function";
+ break;
+ case PCRE_ERROR_BADENDIANNESS:
+ errmsg= "pcre_exec: compiled pattern passed to wrong endianness processor";
+ break;
+ case PCRE_ERROR_JIT_BADOPTION:
+ errmsg= "pcre_exec: bad jit option";
+ break;
+ case PCRE_ERROR_BADLENGTH:
+ errmsg= "pcre_exec: negative length";
+ break;
default:
/*
As other error codes should normally not happen,
@@ -5399,8 +5470,8 @@ int Regexp_processor_pcre::pcre_exec_with_warn(const pcre *code,
bool Regexp_processor_pcre::exec(const char *str, int length, int offset)
{
- m_pcre_exec_rc= pcre_exec_with_warn(m_pcre, NULL, str, length, offset, 0,
- m_SubStrVec, m_subpatterns_needed * 3);
+ m_pcre_exec_rc= pcre_exec_with_warn(m_pcre, &m_pcre_extra, str, length, offset, 0,
+ m_SubStrVec, array_elements(m_SubStrVec));
return false;
}
@@ -5410,10 +5481,10 @@ bool Regexp_processor_pcre::exec(String *str, int offset,
{
if (!(str= convert_if_needed(str, &subject_converter)))
return true;
- m_pcre_exec_rc= pcre_exec_with_warn(m_pcre, NULL,
+ m_pcre_exec_rc= pcre_exec_with_warn(m_pcre, &m_pcre_extra,
str->c_ptr_safe(), str->length(),
offset, 0,
- m_SubStrVec, m_subpatterns_needed * 3);
+ m_SubStrVec, array_elements(m_SubStrVec));
if (m_pcre_exec_rc > 0)
{
uint i;
@@ -5471,7 +5542,7 @@ Item_func_regex::fix_length_and_dec()
if (agg_arg_charsets_for_comparison(cmp_collation, args, 2))
return;
- re.init(cmp_collation.collation, 0, 0);
+ re.init(cmp_collation.collation, 0);
re.fix_owner(this, args[0], args[1]);
}
@@ -5495,7 +5566,7 @@ Item_func_regexp_instr::fix_length_and_dec()
if (agg_arg_charsets_for_comparison(cmp_collation, args, 2))
return;
- re.init(cmp_collation.collation, 0, 1);
+ re.init(cmp_collation.collation, 0);
re.fix_owner(this, args[0], args[1]);
max_length= MY_INT32_NUM_DECIMAL_DIGITS; // See also Item_func_locate
}
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index e21e074a7a3..f19cae72cb5 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -2554,6 +2554,7 @@ public:
class Regexp_processor_pcre
{
pcre *m_pcre;
+ pcre_extra m_pcre_extra;
bool m_conversion_is_needed;
bool m_is_const;
int m_library_flags;
@@ -2562,7 +2563,6 @@ class Regexp_processor_pcre
String m_prev_pattern;
int m_pcre_exec_rc;
int m_SubStrVec[30];
- uint m_subpatterns_needed;
void pcre_exec_warn(int rc) const;
int pcre_exec_with_warn(const pcre *code, const pcre_extra *extra,
const char *subject, int length, int startoffset,
@@ -2576,11 +2576,14 @@ public:
m_pcre(NULL), m_conversion_is_needed(true), m_is_const(0),
m_library_flags(0),
m_data_charset(&my_charset_utf8_general_ci),
- m_library_charset(&my_charset_utf8_general_ci),
- m_subpatterns_needed(0)
- {}
+ m_library_charset(&my_charset_utf8_general_ci)
+ {
+ m_pcre_extra.flags= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
+ m_pcre_extra.match_limit_recursion= 100L;
+ }
int default_regex_flags();
- void init(CHARSET_INFO *data_charset, int extra_flags, uint nsubpatterns_arg)
+ void set_recursion_limit(THD *);
+ void init(CHARSET_INFO *data_charset, int extra_flags)
{
m_library_flags= default_regex_flags() | extra_flags |
(data_charset != &my_charset_bin ?
@@ -2594,7 +2597,6 @@ public:
m_conversion_is_needed= (data_charset != &my_charset_bin) &&
!my_charset_same(data_charset, m_library_charset);
- m_subpatterns_needed= nsubpatterns_arg;
}
void fix_owner(Item_func *owner, Item *subject_arg, Item *pattern_arg);
bool compile(String *pattern, bool send_error);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 63a3937a12e..6fe6ddecc10 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2015, Oracle and/or its affiliates.
- Copyright (c) 2009, 2015, MariaDB
+ Copyright (c) 2009, 2017, 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
@@ -1730,6 +1730,7 @@ my_decimal *Item_func_mod::decimal_op(my_decimal *decimal_value)
return decimal_value;
case E_DEC_DIV_ZERO:
signal_divide_by_null();
+ /* fall through */
default:
null_value= 1;
return 0;
@@ -3649,6 +3650,7 @@ longlong Item_master_gtid_wait::val_int()
{
DBUG_ASSERT(fixed == 1);
longlong result= 0;
+ String *gtid_pos = args[0]->val_str(&value);
if (args[0]->null_value)
{
@@ -3660,7 +3662,6 @@ longlong Item_master_gtid_wait::val_int()
#ifdef HAVE_REPLICATION
THD* thd= current_thd;
longlong timeout_us;
- String *gtid_pos = args[0]->val_str(&value);
if (arg_count==2 && !args[1]->null_value)
timeout_us= (longlong)(1e6*args[1]->val_real());
diff --git a/sql/item_func.h b/sql/item_func.h
index 077f69fe0f5..03eb01bbcc9 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -1622,7 +1622,11 @@ public:
longlong val_int();
const char *func_name() const { return "coercibility"; }
void fix_length_and_dec() { max_length=10; maybe_null= 0; }
- table_map not_null_tables() const { return 0; }
+ bool eval_not_null_tables(void *)
+ {
+ not_null_tables_cache= 0;
+ return false;
+ }
Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond)
{ return this; }
bool const_item() const { return true; }
@@ -1953,7 +1957,11 @@ public:
}
}
void cleanup();
- table_map not_null_tables() const { return 0; }
+ bool eval_not_null_tables(void *opt_arg)
+ {
+ not_null_tables_cache= 0;
+ return 0;
+ }
bool is_expensive() { return 1; }
virtual void print(String *str, enum_query_type query_type);
bool check_vcol_func_processor(void *arg)
@@ -2201,7 +2209,7 @@ public:
:Item_long_func(thd, a, b) {}
longlong val_int();
const char *func_name() const { return "master_gtid_wait"; }
- void fix_length_and_dec() { max_length= 2; maybe_null=0;}
+ void fix_length_and_dec() { max_length=2; }
bool check_vcol_func_processor(void *arg)
{
return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE);
@@ -2482,7 +2490,11 @@ public:
bool is_expensive_processor(void *arg) { return TRUE; }
enum Functype functype() const { return FT_FUNC; }
const char *func_name() const { return "match"; }
- table_map not_null_tables() const { return 0; }
+ bool eval_not_null_tables(void *opt_arg)
+ {
+ not_null_tables_cache= 0;
+ return 0;
+ }
bool fix_fields(THD *thd, Item **ref);
bool eq(const Item *, bool binary_cmp) const;
/* The following should be safe, even if we compare doubles */
@@ -2769,6 +2781,11 @@ public:
clone->sp_result_field= NULL;
return clone;
}
+ bool eval_not_null_tables(void *opt_arg)
+ {
+ not_null_tables_cache= 0;
+ return 0;
+ }
};
@@ -2863,8 +2880,12 @@ public:
my_decimal *val_decimal(my_decimal *);
void fix_length_and_dec();
const char *func_name() const { return "last_value"; }
- table_map not_null_tables() const { return 0; }
const Type_handler *type_handler() const { return last_value->type_handler(); }
+ bool eval_not_null_tables(void *)
+ {
+ not_null_tables_cache= 0;
+ return 0;
+ }
bool const_item() const { return 0; }
void evaluate_sideeffects();
void update_used_tables()
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 4fcff4c0d2e..fb7a60f356e 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -225,7 +225,7 @@ String *Item_func_sha2::val_str_ascii(String *str)
break;
case 0: // SHA-256 is the default
digest_length= 256;
- /* fall trough */
+ /* fall through */
case 256:
my_sha256(digest_buf, input_ptr, input_len);
break;
@@ -271,7 +271,7 @@ void Item_func_sha2::fix_length_and_dec()
switch (sha_variant) {
case 0: // SHA-256 is the default
sha_variant= 256;
- /* fall trough */
+ /* fall through */
case 512:
case 384:
case 256:
@@ -1349,7 +1349,7 @@ void Item_func_regexp_replace::fix_length_and_dec()
if (agg_arg_charsets_for_string_result_with_comparison(collation, args, 3))
return;
max_length= MAX_BLOB_WIDTH;
- re.init(collation.collation, 0, 10);
+ re.init(collation.collation, 0);
re.fix_owner(this, args[0], args[1]);
}
@@ -1484,7 +1484,7 @@ void Item_func_regexp_substr::fix_length_and_dec()
if (agg_arg_charsets_for_string_result_with_comparison(collation, args, 2))
return;
fix_char_length(args[0]->max_char_length());
- re.init(collation.collation, 0, 10);
+ re.init(collation.collation, 0);
re.fix_owner(this, args[0], args[1]);
}
@@ -5163,7 +5163,7 @@ bool Item_dyncol_get::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
goto null;
case DYN_COL_INT:
signed_value= 1; // For error message
- /* fall_trough */
+ /* fall through */
case DYN_COL_UINT:
if (signed_value || val.x.ulong_value <= LONGLONG_MAX)
{
@@ -5177,7 +5177,7 @@ bool Item_dyncol_get::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
}
/* let double_to_datetime_with_warn() issue the warning message */
val.x.double_value= static_cast<double>(ULONGLONG_MAX);
- /* fall_trough */
+ /* fall through */
case DYN_COL_DOUBLE:
if (double_to_datetime_with_warn(val.x.double_value, ltime, fuzzy_date,
0 /* TODO */))
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 09fbf3e239c..dd362cbc15e 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -1425,8 +1425,9 @@ Item_in_subselect::Item_in_subselect(THD *thd, Item * left_exp,
st_select_lex *select_lex):
Item_exists_subselect(thd), left_expr_cache(0), first_execution(TRUE),
in_strategy(SUBS_NOT_TRANSFORMED),
- pushed_cond_guards(NULL), is_jtbm_merged(FALSE), is_jtbm_const_tab(FALSE),
- is_flattenable_semijoin(FALSE), is_registered_semijoin(FALSE),
+ pushed_cond_guards(NULL), do_not_convert_to_sj(FALSE), is_jtbm_merged(FALSE),
+ is_jtbm_const_tab(FALSE), is_flattenable_semijoin(FALSE),
+ is_registered_semijoin(FALSE),
upper_item(0)
{
DBUG_ENTER("Item_in_subselect::Item_in_subselect");
@@ -2587,6 +2588,27 @@ bool Item_in_subselect::inject_in_to_exists_cond(JOIN *join_arg)
DBUG_ENTER("Item_in_subselect::inject_in_to_exists_cond");
DBUG_ASSERT(thd == join_arg->thd);
+ if (select_lex->min_max_opt_list.elements)
+ {
+ /*
+ MIN/MAX optimizations have been applied to Item_sum objects
+ of the subquery this subquery predicate in opt_sum_query().
+ Injection of new condition invalidates this optimizations.
+ Thus those optimizations must be rolled back.
+ */
+ List_iterator_fast<Item_sum> it(select_lex->min_max_opt_list);
+ Item_sum *item;
+ while ((item= it++))
+ {
+ item->clear();
+ item->reset_forced_const();
+ }
+ if (where_item)
+ where_item->update_used_tables();
+ if (having_item)
+ having_item->update_used_tables();
+ }
+
if (where_item)
{
List<Item> *and_args= NULL;
@@ -3761,7 +3783,10 @@ int subselect_single_select_engine::exec()
}
}
if (item->engine_changed(this))
+ {
+ thd->lex->current_select= save_select;
DBUG_RETURN(1);
+ }
}
if (select_lex->uncacheable &&
select_lex->uncacheable != UNCACHEABLE_EXPLAIN
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index cb60b646979..6112c1c22f4 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -505,6 +505,8 @@ public:
Item *left_expr_orig;
/* Priority of this predicate in the convert-to-semi-join-nest process. */
int sj_convert_priority;
+ /* May be TRUE only for the candidates to semi-join conversion */
+ bool do_not_convert_to_sj;
/*
Types of left_expr and subquery's select list allow to perform subquery
materialization. Currently, we set this to FALSE when it as well could
@@ -595,8 +597,8 @@ public:
Item_in_subselect(THD *thd_arg):
Item_exists_subselect(thd_arg), left_expr_cache(0), first_execution(TRUE),
in_strategy(SUBS_NOT_TRANSFORMED),
- pushed_cond_guards(NULL), func(NULL), is_jtbm_merged(FALSE),
- is_jtbm_const_tab(FALSE), upper_item(0) {}
+ pushed_cond_guards(NULL), func(NULL), do_not_convert_to_sj(FALSE),
+ is_jtbm_merged(FALSE), is_jtbm_const_tab(FALSE), upper_item(0) {}
void cleanup();
subs_type substype() { return IN_SUBS; }
void reset()
@@ -651,6 +653,8 @@ public:
*/
int get_identifier();
+ void block_conversion_to_sj () { do_not_convert_to_sj= TRUE; }
+
bool test_strategy(uchar strategy)
{ return MY_TEST(in_strategy & strategy); }
diff --git a/sql/item_sum.h b/sql/item_sum.h
index 65306ab6f48..a160d0ee522 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -485,6 +485,7 @@ public:
used_tables_cache= 0;
const_item_cache= true;
}
+ void reset_forced_const() { const_item_cache= false; }
virtual bool const_during_execution() const { return false; }
virtual void print(String *str, enum_query_type query_type);
void fix_num_length_and_dec();
diff --git a/sql/item_windowfunc.cc b/sql/item_windowfunc.cc
index 6ab903a81bb..a216930cad6 100644
--- a/sql/item_windowfunc.cc
+++ b/sql/item_windowfunc.cc
@@ -71,7 +71,7 @@ Item_window_func::fix_fields(THD *thd, Item **ref)
{
DBUG_ASSERT(fixed == 0);
- enum_parsing_place place= thd->lex->current_select->parsing_place;
+ enum_parsing_place place= thd->lex->current_select->context_analysis_place;
if (!(place == SELECT_LIST || place == IN_ORDER_BY))
{
diff --git a/sql/lock.cc b/sql/lock.cc
index 12de6ae0616..a34613fb7fe 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -422,6 +422,7 @@ void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock)
void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock, bool free_lock)
{
DBUG_ENTER("mysql_unlock_tables");
+ bool errors= thd->is_error();
THD_STAGE_INFO(thd, stage_unlocking_tables);
if (sql_lock->table_count)
@@ -430,6 +431,8 @@ void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock, bool free_lock)
thr_multi_unlock(sql_lock->locks, sql_lock->lock_count, 0);
if (free_lock)
my_free(sql_lock);
+ if (!errors)
+ thd->clear_error();
DBUG_VOID_RETURN;
}
diff --git a/sql/log.cc b/sql/log.cc
index 0ffa4a5a82d..166180e08a4 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -5681,7 +5681,11 @@ int THD::binlog_write_table_map(TABLE *table, bool is_transactional,
/* Annotate event should be written not more than once */
*with_annotate= 0;
if ((error= writer.write(&anno)))
+ {
+ if (my_errno == EFBIG)
+ cache_data->set_incident();
DBUG_RETURN(error);
+ }
}
if ((error= writer.write(&the_event)))
DBUG_RETURN(error);
@@ -9220,8 +9224,10 @@ void TC_LOG_MMAP::close()
mysql_cond_destroy(&COND_pool);
mysql_cond_destroy(&COND_active);
mysql_cond_destroy(&COND_queue_busy);
+ /* fall through */
case 5:
data[0]='A'; // garble the first (signature) byte, in case mysql_file_delete fails
+ /* fall through */
case 4:
for (i=0; i < npages; i++)
{
@@ -9230,10 +9236,13 @@ void TC_LOG_MMAP::close()
mysql_mutex_destroy(&pages[i].lock);
mysql_cond_destroy(&pages[i].cond);
}
+ /* fall through */
case 3:
my_free(pages);
+ /* fall through */
case 2:
my_munmap((char*)data, (size_t)file_length);
+ /* fall through */
case 1:
mysql_file_close(fd, MYF(0));
}
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 3c062975041..24bcaf8a60b 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -8404,7 +8404,6 @@ int Xid_log_event::do_apply_event(rpl_group_info *rgi)
consistent.
*/
#ifdef WITH_WSREP
- /*Set wsrep_affected_rows = 0 */
thd->wsrep_affected_rows= 0;
#endif
diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc
index 9ba29ddb0f6..8f1cfe17656 100644
--- a/sql/log_event_old.cc
+++ b/sql/log_event_old.cc
@@ -1587,7 +1587,7 @@ int Old_rows_log_event::do_apply_event(rpl_group_info *rgi)
rli->report(ERROR_LEVEL, thd->net.last_errno, NULL,
"Error in %s event: row application failed. %s",
get_type_str(), thd->net.last_error);
- thd->is_slave_error = 1;
+ thd->is_slave_error= 1;
break;
}
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index d7c46071c38..6da1bd75531 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -105,6 +105,7 @@
#include "sp_rcontext.h"
#include "sp_cache.h"
#include "sql_reload.h" // reload_acl_and_cache
+#include "pcre.h"
#ifdef HAVE_POLL_H
#include <poll.h>
@@ -3721,6 +3722,7 @@ static void init_libstrings()
#endif
}
+ulonglong my_pcre_frame_size;
static void init_pcre()
{
@@ -3728,6 +3730,8 @@ static void init_pcre()
pcre_free= pcre_stack_free= my_str_free_mysqld;
#ifndef EMBEDDED_LIBRARY
pcre_stack_guard= check_enough_stack_size_slow;
+ /* See http://pcre.org/original/doc/html/pcrestack.html */
+ my_pcre_frame_size= -pcre_exec(NULL, NULL, NULL, -999, -999, 0, NULL, 0) + 16;
#endif
}
@@ -7297,13 +7301,6 @@ struct my_option my_long_options[]=
&max_binlog_dump_events, &max_binlog_dump_events, 0,
GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#endif /* HAVE_REPLICATION */
-#ifdef SAFE_MUTEX
- {"debug-mutex-deadlock-detector", 0,
- "Enable checking of wrong mutex usage.",
- &safe_mutex_deadlock_detector,
- &safe_mutex_deadlock_detector,
- 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
-#endif
{"debug-no-sync", 0,
"Disables system sync calls. Only for running tests or debugging!",
&my_disable_sync, &my_disable_sync, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -8252,7 +8249,7 @@ static int show_default_keycache(THD *thd, SHOW_VAR *var, char *buff,
{
struct st_data {
KEY_CACHE_STATISTICS stats;
- SHOW_VAR var[8];
+ SHOW_VAR var[9];
} *data;
SHOW_VAR *v;
@@ -9363,7 +9360,10 @@ mysql_getopt_value(const char *name, uint length,
return (uchar**) &key_cache->changed_blocks_hash_size;
}
}
+ /* We return in all cases above. Let us silence -Wimplicit-fallthrough */
+ DBUG_ASSERT(0);
#ifdef HAVE_REPLICATION
+ /* fall through */
case OPT_REPLICATE_DO_DB:
case OPT_REPLICATE_DO_TABLE:
case OPT_REPLICATE_IGNORE_DB:
diff --git a/sql/mysqld.h b/sql/mysqld.h
index b7de4ecc324..38e42dd61f1 100644
--- a/sql/mysqld.h
+++ b/sql/mysqld.h
@@ -133,7 +133,7 @@ extern ulong slave_retried_transactions;
extern ulong slave_run_triggers_for_rbr;
extern ulonglong slave_type_conversions_options;
extern my_bool read_only, opt_readonly;
-extern my_bool lower_case_file_system;
+extern MYSQL_PLUGIN_IMPORT my_bool lower_case_file_system;
extern my_bool opt_enable_named_pipe, opt_sync_frm, opt_allow_suspicious_udfs;
extern my_bool opt_secure_auth;
extern const char *current_dbug_option;
@@ -527,6 +527,8 @@ extern pthread_t signal_thread;
extern struct st_VioSSLFd * ssl_acceptor_fd;
#endif /* HAVE_OPENSSL */
+extern ulonglong my_pcre_frame_size;
+
/*
The following variables were under INNODB_COMPABILITY_HOOKS
*/
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 284f4348080..9161dee7836 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -6955,7 +6955,10 @@ QUICK_SELECT_I *TRP_ROR_UNION::make_quick(PARAM *param,
{
if (!(quick= (*scan)->make_quick(param, FALSE, &quick_roru->alloc)) ||
quick_roru->push_quick_back(quick))
+ {
+ delete quick_roru;
DBUG_RETURN(NULL);
+ }
}
quick_roru->records= records;
quick_roru->read_time= read_cost;
@@ -7501,7 +7504,7 @@ SEL_TREE *Item_bool_func::get_full_func_mm_tree(RANGE_OPT_PARAM *param,
param->current_table);
#ifdef HAVE_SPATIAL
Field::geometry_type sav_geom_type;
- LINT_INIT(sav_geom_type);
+ LINT_INIT_STRUCT(sav_geom_type);
if (field_item->field->type() == MYSQL_TYPE_GEOMETRY)
{
@@ -10795,9 +10798,7 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
*/
thd->mem_root= old_root;
- if (!quick || create_err)
- return 0; /* no ranges found */
- if (quick->init())
+ if (!quick || create_err || quick->init())
goto err;
quick->records= records;
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index b18fb8f2ae5..1b245342f76 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -980,6 +980,25 @@ bool check_for_outer_joins(List<TABLE_LIST> *join_list)
}
+void find_and_block_conversion_to_sj(Item *to_find,
+ List_iterator_fast<Item_in_subselect> &li)
+{
+ if (to_find->type() != Item::SUBSELECT_ITEM ||
+ ((Item_subselect *) to_find)->substype() != Item_subselect::IN_SUBS)
+ return;
+ Item_in_subselect *in_subq;
+ li.rewind();
+ while ((in_subq= li++))
+ {
+ if (in_subq == to_find)
+ {
+ in_subq->block_conversion_to_sj();
+ return;
+ }
+ }
+}
+
+
/*
Convert semi-join subquery predicates into semi-join join nests
@@ -1032,7 +1051,6 @@ bool convert_join_subqueries_to_semijoins(JOIN *join)
Query_arena *arena, backup;
Item_in_subselect *in_subq;
THD *thd= join->thd;
- List_iterator<TABLE_LIST> ti(join->select_lex->leaf_tables);
DBUG_ENTER("convert_join_subqueries_to_semijoins");
if (join->select_lex->sj_subselects.is_empty())
@@ -1050,6 +1068,89 @@ bool convert_join_subqueries_to_semijoins(JOIN *join)
subq_sel->update_used_tables();
}
+ /*
+ Check all candidates to semi-join conversion that occur
+ in ON expressions of outer join. Set the flag blocking
+ this conversion for them.
+ */
+ TABLE_LIST *tbl;
+ List_iterator<TABLE_LIST> ti(join->select_lex->leaf_tables);
+ while ((tbl= ti++))
+ {
+ TABLE_LIST *embedded;
+ TABLE_LIST *embedding= tbl;
+ do
+ {
+ embedded= embedding;
+ bool block_conversion_to_sj= false;
+ if (embedded->on_expr)
+ {
+ /*
+ Conversion of an IN subquery predicate into semi-join
+ is blocked now if the predicate occurs:
+ - in the ON expression of an outer join
+ - in the ON expression of an inner join embedded directly
+ or indirectly in the inner nest of an outer join
+ */
+ for (TABLE_LIST *tl= embedded; tl; tl= tl->embedding)
+ {
+ if (tl->outer_join)
+ {
+ block_conversion_to_sj= true;
+ break;
+ }
+ }
+ }
+ if (block_conversion_to_sj)
+ {
+ Item *cond= embedded->on_expr;
+ if (!cond)
+ ;
+ else if (cond->type() != Item::COND_ITEM)
+ find_and_block_conversion_to_sj(cond, li);
+ else if (((Item_cond*) cond)->functype() ==
+ Item_func::COND_AND_FUNC)
+ {
+ Item *item;
+ List_iterator<Item> it(*(((Item_cond*) cond)->argument_list()));
+ while ((item= it++))
+ {
+ find_and_block_conversion_to_sj(item, li);
+ }
+ }
+ }
+ embedding= embedded->embedding;
+ }
+ while (embedding &&
+ embedding->nested_join->join_list.head() == embedded);
+ }
+
+ /*
+ Block conversion to semi-joins for those candidates that
+ are encountered in the WHERE condition of the multi-table view
+ with CHECK OPTION if this view is used in UPDATE/DELETE.
+ (This limitation can be, probably, easily lifted.)
+ */
+ li.rewind();
+ while ((in_subq= li++))
+ {
+ if (in_subq->emb_on_expr_nest != NO_JOIN_NEST &&
+ in_subq->emb_on_expr_nest->effective_with_check)
+ {
+ in_subq->block_conversion_to_sj();
+ }
+ }
+
+ if (join->select_options & SELECT_STRAIGHT_JOIN)
+ {
+ /* Block conversion to semijoins for all candidates */
+ li.rewind();
+ while ((in_subq= li++))
+ {
+ in_subq->block_conversion_to_sj();
+ }
+ }
+
li.rewind();
/* First, convert child join's subqueries. We proceed bottom-up here */
while ((in_subq= li++))
@@ -1068,8 +1169,10 @@ bool convert_join_subqueries_to_semijoins(JOIN *join)
if (convert_join_subqueries_to_semijoins(child_join))
DBUG_RETURN(TRUE);
+
+
in_subq->sj_convert_priority=
- MY_TEST(in_subq->emb_on_expr_nest != NO_JOIN_NEST) * MAX_TABLES * 2 +
+ MY_TEST(in_subq->do_not_convert_to_sj) * MAX_TABLES * 2 +
in_subq->is_correlated * MAX_TABLES + child_join->outer_tables;
}
@@ -1102,7 +1205,7 @@ bool convert_join_subqueries_to_semijoins(JOIN *join)
bool remove_item= TRUE;
/* Stop processing if we've reached a subquery that's attached to the ON clause */
- if (in_subq->emb_on_expr_nest != NO_JOIN_NEST)
+ if (in_subq->do_not_convert_to_sj)
break;
if (in_subq->is_flattenable_semijoin)
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index 9bc21ab3ac3..ab587b8b279 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2011, Oracle and/or its affiliates.
- Copyright (c) 2008-2011 Monty Program Ab
+ Copyright (c) 2008, 2017, MariaDB Corporation.
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
@@ -254,6 +254,8 @@ int opt_sum_query(THD *thd,
int error= 0;
DBUG_ENTER("opt_sum_query");
+ thd->lex->current_select->min_max_opt_list.empty();
+
if (conds)
where_tables= conds->used_tables();
@@ -447,7 +449,14 @@ int opt_sum_query(THD *thd,
item_sum->aggregator_clear();
}
else
+ {
item_sum->reset_and_add();
+ /*
+ Save a reference to the item for possible rollback
+ of the min/max optimizations for this select
+ */
+ thd->lex->current_select->min_max_opt_list.push_back(item_sum);
+ }
item_sum->make_const();
recalc_const_item= 1;
break;
@@ -1042,6 +1051,7 @@ static int maxmin_in_range(bool max_fl, Field* field, COND *cond)
case Item_func::LT_FUNC:
case Item_func::LE_FUNC:
less_fl= 1;
+ /* fall through */
case Item_func::GT_FUNC:
case Item_func::GE_FUNC:
{
diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc
index a2617de2757..c385434e41e 100644
--- a/sql/rpl_gtid.cc
+++ b/sql/rpl_gtid.cc
@@ -2045,7 +2045,7 @@ gtid_waiting::wait_for_pos(THD *thd, String *gtid_str, longlong timeout_us)
{
case -1:
status_var_increment(thd->status_var.master_gtid_wait_timeouts);
- /* Deliberate fall through. */
+ /* fall through */
case 0:
status_var_add(thd->status_var.master_gtid_wait_time,
microsecond_interval_timer() - before);
diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc
index 60c887965fb..e90557efd0d 100644
--- a/sql/rpl_mi.cc
+++ b/sql/rpl_mi.cc
@@ -41,7 +41,7 @@ Master_info::Master_info(LEX_CSTRING *connection_name_arg,
master_id(0), prev_master_id(0),
using_gtid(USE_GTID_NO), events_queued_since_last_gtid(0),
gtid_reconnect_event_skip_count(0), gtid_event_seen(false),
- in_start_all_slaves(0), in_stop_all_slaves(0),
+ in_start_all_slaves(0), in_stop_all_slaves(0), in_flush_all_relay_logs(0),
users(0), killed(0)
{
char *tmp;
@@ -663,7 +663,7 @@ file '%s')", fname);
mi->connect_retry= (uint) connect_retry;
mi->ssl= (my_bool) ssl;
mi->ssl_verify_server_cert= ssl_verify_server_cert;
- mi->heartbeat_period= master_heartbeat_period;
+ mi->heartbeat_period= MY_MIN(SLAVE_MAX_HEARTBEAT_PERIOD, master_heartbeat_period);
}
DBUG_PRINT("master_info",("log_file_name: %s position: %ld",
mi->master_log_name,
@@ -798,8 +798,8 @@ int flush_master_info(Master_info* mi,
contents of file). But because of number of lines in the first line
of file we don't care about this garbage.
*/
- char heartbeat_buf[sizeof(mi->heartbeat_period) * 4]; // buffer to suffice always
- sprintf(heartbeat_buf, "%.3f", mi->heartbeat_period);
+ char heartbeat_buf[FLOATING_POINT_BUFFER];
+ my_fcvt(mi->heartbeat_period, 3, heartbeat_buf, NULL);
my_b_seek(file, 0L);
my_b_printf(file,
"%u\n%s\n%s\n%s\n%s\n%s\n%d\n%d\n%d\n%s\n%s\n%s\n%s\n%s\n%d\n%s\n%s\n%s\n%s\n%d\n%s\n%s\n"
@@ -1979,4 +1979,53 @@ void prot_store_ids(THD *thd, DYNAMIC_ARRAY *ids)
return;
}
+bool Master_info_index::flush_all_relay_logs()
+{
+ DBUG_ENTER("flush_all_relay_logs");
+ bool result= false;
+ int error= 0;
+ mysql_mutex_lock(&LOCK_active_mi);
+ for (uint i= 0; i< master_info_hash.records; i++)
+ {
+ Master_info *mi;
+ mi= (Master_info *) my_hash_element(&master_info_hash, i);
+ mi->in_flush_all_relay_logs= 0;
+ }
+ for (uint i=0; i < master_info_hash.records;)
+ {
+ Master_info *mi;
+ mi= (Master_info *)my_hash_element(&master_info_hash, i);
+ DBUG_ASSERT(mi);
+
+ if (mi->in_flush_all_relay_logs)
+ {
+ i++;
+ continue;
+ }
+ mi->in_flush_all_relay_logs= 1;
+
+ mysql_mutex_lock(&mi->sleep_lock);
+ mi->users++; // Mark used
+ mysql_mutex_unlock(&mi->sleep_lock);
+ mysql_mutex_unlock(&LOCK_active_mi);
+
+ mysql_mutex_lock(&mi->data_lock);
+ error= rotate_relay_log(mi);
+ mysql_mutex_unlock(&mi->data_lock);
+ mi->release();
+ mysql_mutex_lock(&LOCK_active_mi);
+
+ if (error)
+ {
+ result= true;
+ break;
+ }
+ /* Restart from first element as master_info_hash may have changed */
+ i= 0;
+ continue;
+ }
+ mysql_mutex_unlock(&LOCK_active_mi);
+ DBUG_RETURN(result);
+}
+
#endif /* HAVE_REPLICATION */
diff --git a/sql/rpl_mi.h b/sql/rpl_mi.h
index 535abd25f6d..ccc1be6e5ce 100644
--- a/sql/rpl_mi.h
+++ b/sql/rpl_mi.h
@@ -302,6 +302,7 @@ class Master_info : public Slave_reporting_capability
/* gtid_event_seen is false until we receive first GTID event from master. */
bool gtid_event_seen;
bool in_start_all_slaves, in_stop_all_slaves;
+ bool in_flush_all_relay_logs;
uint users; /* Active user for object */
uint killed;
@@ -354,6 +355,7 @@ public:
bool start_all_slaves(THD *thd);
bool stop_all_slaves(THD *thd);
void free_connections();
+ bool flush_all_relay_logs();
};
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index 1f282e6aee5..cfc544cc1bd 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -5202,7 +5202,7 @@ ER_FRM_UNKNOWN_TYPE
rus "Файл '%-.192s' содержит неизвестный тип '%-.64s' в заголовке"
ukr "Файл '%-.192s' має невідомий тип '%-.64s' у заголовку"
ER_WRONG_OBJECT
- eng "'%-.192s.%-.192s' is not %s"
+ eng "'%-.192s.%-.192s' is not of type '%s'"
ger "'%-.192s.%-.192s' ist nicht %s"
rus "'%-.192s.%-.192s' - не %s"
ukr "'%-.192s.%-.192s' не є %s"
diff --git a/sql/slave.cc b/sql/slave.cc
index 641bdae9e31..a7f0f003e5c 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2016, Oracle and/or its affiliates.
- Copyright (c) 2009, 2016, MariaDB
+ Copyright (c) 2009, 2017, 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
@@ -6286,9 +6286,8 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len)
mi->last_queued_gtid.seq_no == 1000)
goto skip_relay_logging;
});
- /* Fall through to default case ... */
#endif
-
+ /* fall through */
default:
default_action:
DBUG_EXECUTE_IF("kill_slave_io_after_2_events",
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index f8ad3c305a7..c87a15ff927 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -1,6 +1,6 @@
/*
Copyright (c) 2002, 2016, Oracle and/or its affiliates.
- Copyright (c) 2011, 2016, MariaDB
+ Copyright (c) 2011, 2017, 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_acl.cc b/sql/sql_acl.cc
index d63a2f2bc51..433d48a3de4 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -11698,12 +11698,6 @@ void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant,
/* global privileges */
grant->privilege= sctx->master_access;
- if (!sctx->priv_user[0] && !sctx->priv_role[0])
- {
- DBUG_PRINT("info", ("privilege 0x%lx", grant->privilege));
- DBUG_VOID_RETURN; // it is slave
- }
-
if (!thd->db || strcmp(db, thd->db))
{
/* db privileges */
diff --git a/sql/sql_audit.cc b/sql/sql_audit.cc
index 8a523ebbf4b..8134adca13f 100644
--- a/sql/sql_audit.cc
+++ b/sql/sql_audit.cc
@@ -240,7 +240,7 @@ void mysql_audit_finalize()
/**
Initialize an Audit plug-in
-
+
@param[in] plugin
@retval FALSE OK
@@ -251,12 +251,13 @@ int initialize_audit_plugin(st_plugin_int *plugin)
{
st_mysql_audit *data= (st_mysql_audit*) plugin->plugin->info;
- if (!data->event_notify || !data->class_mask[0]) {
+ if (!data->event_notify || !data->class_mask[0])
+ {
sql_print_error("Plugin '%s' has invalid data.",
plugin->name.str);
return 1;
}
-
+
if (plugin->plugin->init && plugin->plugin->init(NULL))
{
sql_print_error("Plugin '%s' init function returned error.",
@@ -266,7 +267,7 @@ int initialize_audit_plugin(st_plugin_int *plugin)
/* Make the interface info more easily accessible */
plugin->data= plugin->plugin->info;
-
+
/* Add the bits the plugin is interested in to the global mask */
mysql_mutex_lock(&LOCK_audit_mask);
add_audit_mask(mysql_global_audit_mask, data->class_mask);
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index b2927c89fda..89afef4eaf7 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
- Copyright (c) 2010, 2013, Monty Program Ab
+ Copyright (c) 2010, 2017, MariaDB Corporation
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
@@ -1466,12 +1466,6 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
(int)flags.autocommit));
/*
- Make InnoDB to release the adaptive hash index latch before
- acquiring the query cache mutex.
- */
- ha_release_temporary_latches(thd);
-
- /*
A table- or a full flush operation can potentially take a long time to
finish. We choose not to wait for them and skip caching statements
instead.
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 076ae8b9923..740d5648214 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -2818,13 +2818,6 @@ int select_send::send_data(List<Item> &items)
if (thd->killed == ABORT_QUERY)
DBUG_RETURN(FALSE);
- /*
- We may be passing the control from mysqld to the client: release the
- InnoDB adaptive hash S-latch to avoid thread deadlocks if it was reserved
- by thd
- */
- ha_release_temporary_latches(thd);
-
protocol->prepare_for_resend();
if (protocol->send_result_set_row(&items))
{
@@ -2844,13 +2837,6 @@ int select_send::send_data(List<Item> &items)
bool select_send::send_eof()
{
/*
- We may be passing the control from mysqld to the client: release the
- InnoDB adaptive hash S-latch to avoid thread deadlocks if it was reserved
- by thd
- */
- ha_release_temporary_latches(thd);
-
- /*
Don't send EOF if we're in error condition (which implies we've already
sent or are sending an error)
*/
@@ -5601,6 +5587,7 @@ bool xid_cache_insert(THD *thd, XID_STATE *xid_state)
break;
case 1:
my_error(ER_XAER_DUPID, MYF(0));
+ /* fall through */
default:
xid_state->xid_cache_element= 0;
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 817be9d939c..02bfb5f402d 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -4697,7 +4697,7 @@ public:
select_result(thd_arg), suppress_my_ok(false)
{
DBUG_ENTER("select_result_interceptor::select_result_interceptor");
- DBUG_PRINT("enter", ("this 0x%lx", (ulong) this));
+ DBUG_PRINT("enter", ("this %p", this));
DBUG_VOID_RETURN;
} /* Remove gcc warning */
uint field_count(List<Item> &fields) const { return 0; }
diff --git a/sql/sql_digest.cc b/sql/sql_digest.cc
index 18106a70475..27c33f1c64b 100644
--- a/sql/sql_digest.cc
+++ b/sql/sql_digest.cc
@@ -1,4 +1,5 @@
/* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2017, MariaDB Corporation.
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
@@ -454,7 +455,8 @@ sql_digest_state* digest_add_token(sql_digest_state *state,
}
} while (found_unary);
}
- /* fall through, for case NULL_SYM below */
+ /* for case NULL_SYM below */
+ /* fall through */
case LEX_HOSTNAME:
case TEXT_STRING:
case NCHAR_STRING:
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 8085e3ded1b..16ab4ee650a 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2016, Oracle and/or its affiliates.
- Copyright (c) 2010, 2016, MariaDB
+ Copyright (c) 2010, 2017, 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
@@ -699,9 +699,9 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
bool using_bulk_insert= 0;
uint value_count;
ulong counter = 1;
- ulong iteration= 0;
+ /* counter of iteration in bulk PS operation*/
+ ulonglong iteration= 0;
ulonglong id;
- ulong bulk_iterations= bulk_parameters_iterations(thd);
COPY_INFO info;
TABLE *table= 0;
List_iterator_fast<List_item> its(values_list);
@@ -769,7 +769,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
DBUG_RETURN(TRUE);
value_count= values->elements;
- DBUG_ASSERT(bulk_iterations > 0);
if (mysql_prepare_insert(thd, table_list, table, fields, values,
update_fields, update_values, duplic, &unused_conds,
FALSE))
@@ -941,6 +940,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
}
do
{
+ DBUG_PRINT("info", ("iteration %llu", iteration));
if (iteration && bulk_parameters_set(thd))
goto abort;
@@ -1061,7 +1061,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
}
its.rewind();
iteration++;
- } while (iteration < bulk_iterations);
+ } while (bulk_parameters_iterations(thd));
values_loop_end:
free_underlaid_joins(thd, &thd->lex->select_lex);
@@ -1208,7 +1208,7 @@ values_loop_end:
retval= thd->lex->explain->send_explain(thd);
goto abort;
}
- if ((bulk_iterations * values_list.elements) == 1 && (!(thd->variables.option_bits & OPTION_WARNINGS) ||
+ if ((iteration * values_list.elements) == 1 && (!(thd->variables.option_bits & OPTION_WARNINGS) ||
!thd->cuted_fields))
{
my_ok(thd, info.copied + info.deleted +
@@ -3753,9 +3753,6 @@ int select_insert::send_data(List<Item> &values)
}
}
- // Release latches in case bulk insert takes a long time
- ha_release_temporary_latches(thd);
-
error= write_record(thd, table, &info);
table->auto_increment_field_not_null= FALSE;
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 4c763f50eaf..ef7ca58fe93 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2014, Oracle and/or its affiliates.
- Copyright (c) 2009, 2016, MariaDB
+ Copyright (c) 2009, 2017, 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
@@ -1477,12 +1477,14 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd)
state= MY_LEX_HEX_NUMBER;
break;
}
+ /* fall through */
case MY_LEX_IDENT_OR_BIN:
if (lip->yyPeek() == '\'')
{ // Found b'bin-number'
state= MY_LEX_BIN_NUMBER;
break;
}
+ /* fall through */
case MY_LEX_IDENT:
const char *start;
#if defined(USE_MB) && defined(USE_MB_IDENT)
@@ -1824,6 +1826,7 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd)
break;
}
/* " used for strings */
+ /* fall through */
case MY_LEX_STRING: // Incomplete text string
{
uint sep;
@@ -2182,6 +2185,7 @@ void st_select_lex::init_query()
leaf_tables_prep.empty();
leaf_tables.empty();
item_list.empty();
+ min_max_opt_list.empty();
join= 0;
having= prep_having= where= prep_where= 0;
cond_pushed_into_where= cond_pushed_into_having= 0;
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 61c13814eeb..08a6936db6e 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -845,6 +845,11 @@ public:
*/
List<Item_func_match> *ftfunc_list;
List<Item_func_match> ftfunc_list_alloc;
+ /*
+ The list of items to which MIN/MAX optimizations of opt_sum_query()
+ have been applied. Used to rollback those optimizations if it's needed.
+ */
+ List<Item_sum> min_max_opt_list;
JOIN *join; /* after JOIN::prepare it is pointer to corresponding JOIN */
List<TABLE_LIST> top_join_list; /* join list of the top level */
List<TABLE_LIST> *join_list; /* list for the currently parsed join */
@@ -906,6 +911,7 @@ public:
/* reserved for exists 2 in */
uint select_n_reserved;
enum_parsing_place parsing_place; /* where we are parsing expression */
+ enum_parsing_place context_analysis_place; /* where we are in prepare */
bool with_sum_func; /* sum function indicator */
ulong table_join_options;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 174d57b99af..fbfbe0f77fb 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -392,7 +392,7 @@ const LEX_STRING command_name[257]={
{ 0, 0 }, //247
{ 0, 0 }, //248
{ 0, 0 }, //249
- { 0, 0 }, //250
+ { C_STRING_WITH_LEN("Bulk_execute") }, //250
{ C_STRING_WITH_LEN("Slave_worker") }, //251
{ C_STRING_WITH_LEN("Slave_IO") }, //252
{ C_STRING_WITH_LEN("Slave_SQL") }, //253
@@ -1754,6 +1754,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
break;
}
+ case COM_STMT_BULK_EXECUTE:
+ {
+ mysqld_stmt_bulk_execute(thd, packet, packet_length);
+ break;
+ }
case COM_STMT_EXECUTE:
{
mysqld_stmt_execute(thd, packet, packet_length);
@@ -3534,8 +3539,8 @@ mysql_execute_command(THD *thd)
MYF(0));
goto error;
}
- /* no break; fall through */
}
+ /* fall through */
case SQLCOM_SHOW_STATUS_PROC:
case SQLCOM_SHOW_STATUS_FUNC:
case SQLCOM_SHOW_DATABASES:
@@ -3549,7 +3554,7 @@ mysql_execute_command(THD *thd)
case SQLCOM_SELECT:
if (WSREP_CLIENT(thd) && wsrep_sync_wait(thd))
goto error;
-
+ /* fall through */
case SQLCOM_SHOW_PLUGINS:
case SQLCOM_SHOW_VARIABLES:
case SQLCOM_SHOW_CHARSETS:
@@ -4391,8 +4396,8 @@ end_with_restore_list:
/* mysql_update return 2 if we need to switch to multi-update */
if (up_result != 2)
break;
- /* Fall through */
}
+ /* Fall through */
case SQLCOM_UPDATE_MULTI:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
@@ -4510,6 +4515,7 @@ end_with_restore_list:
}
#endif
}
+ /* fall through */
case SQLCOM_INSERT:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
@@ -5442,6 +5448,7 @@ end_with_restore_list:
initialize this variable because RESET shares the same code as FLUSH
*/
lex->no_write_to_binlog= 1;
+ /* fall through */
case SQLCOM_FLUSH:
{
int write_to_binlog;
@@ -7354,12 +7361,6 @@ bool check_fk_parent_table_access(THD *thd,
****************************************************************************/
-#if STACK_DIRECTION < 0
-#define used_stack(A,B) (long) (A - B)
-#else
-#define used_stack(A,B) (long) (B - A)
-#endif
-
#ifndef DBUG_OFF
long max_stack_used;
#endif
@@ -7376,7 +7377,7 @@ bool check_stack_overrun(THD *thd, long margin,
{
long stack_used;
DBUG_ASSERT(thd == current_thd);
- if ((stack_used=used_stack(thd->thread_stack,(char*) &stack_used)) >=
+ if ((stack_used= available_stack_size(thd->thread_stack, &stack_used)) >=
(long) (my_thread_stack_size - margin))
{
thd->is_fatal_error= 1;
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index e9fc0f62617..92b9c94e84c 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -1,6 +1,6 @@
/*
Copyright (c) 2005, 2013, Oracle and/or its affiliates.
- Copyright (c) 2010, 2014, SkySQL Ab.
+ Copyright (c) 2010, 2017, MariaDB Corporation.
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
@@ -1864,8 +1864,8 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, const char *list)
switch ((*(p++)= *(list++))) {
case '\0':
list= NULL; /* terminate the loop */
- /* fall through */
#ifndef __WIN__
+ /* fall through */
case ':': /* can't use this as delimiter as it may be drive letter */
#endif
case ';':
@@ -1908,6 +1908,7 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, const char *list)
str->str= p;
continue;
}
+ /* fall through */
default:
str->length++;
continue;
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index a1c352e8b19..f671e45d51a 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -1,5 +1,5 @@
/* Copyright (c) 2002, 2015, Oracle and/or its affiliates.
- Copyright (c) 2008, 2016, MariaDB
+ Copyright (c) 2008, 2017, 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
@@ -164,7 +164,6 @@ public:
Server_side_cursor *cursor;
uchar *packet;
uchar *packet_end;
- ulong iterations;
uint param_count;
uint last_errno;
uint flags;
@@ -183,7 +182,9 @@ public:
*/
uint select_number_after_prepare;
char last_error[MYSQL_ERRMSG_SIZE];
+ my_bool iterations;
my_bool start_param;
+ my_bool read_types;
#ifndef EMBEDDED_LIBRARY
bool (*set_params)(Prepared_statement *st, uchar *data, uchar *data_end,
uchar *read_pos, String *expanded_query);
@@ -213,11 +214,10 @@ public:
uchar *packet_arg, uchar *packet_end_arg);
bool execute_bulk_loop(String *expanded_query,
bool open_cursor,
- uchar *packet_arg, uchar *packet_end_arg,
- ulong iterations);
+ uchar *packet_arg, uchar *packet_end_arg);
bool execute_server_runnable(Server_runnable *server_runnable);
my_bool set_bulk_parameters(bool reset);
- ulong bulk_iterations();
+ bool bulk_iterations() { return iterations; };
/* Destroy this statement */
void deallocate();
bool execute_immediate(const char *query, uint query_length);
@@ -923,6 +923,7 @@ static bool insert_params(Prepared_statement *stmt, uchar *null_array,
for (Item_param **it= begin; it < end; ++it)
{
Item_param *param= *it;
+ param->indicator= STMT_INDICATOR_NONE; // only for bulk parameters
if (!param->has_long_data_value())
{
if (is_param_null(null_array, (uint) (it - begin)))
@@ -967,10 +968,7 @@ static bool insert_bulk_params(Prepared_statement *stmt,
param->reset();
if (!param->has_long_data_value())
{
- if (param->indicators)
- param->indicator= (enum_indicator_type) *((*read_pos)++);
- else
- param->indicator= STMT_INDICATOR_NONE;
+ param->indicator= (enum_indicator_type) *((*read_pos)++);
if ((*read_pos) > data_end)
DBUG_RETURN(1);
switch (param->indicator)
@@ -981,6 +979,8 @@ static bool insert_bulk_params(Prepared_statement *stmt,
param->set_param_func(param, read_pos, (uint) (data_end - (*read_pos)));
if (param->has_no_value())
DBUG_RETURN(1);
+ if (param->convert_str_value(stmt->thd))
+ DBUG_RETURN(1); /* out of memory */
break;
case STMT_INDICATOR_NULL:
param->set_null();
@@ -999,6 +999,36 @@ static bool insert_bulk_params(Prepared_statement *stmt,
DBUG_RETURN(0);
}
+static bool set_conversion_functions(Prepared_statement *stmt,
+ uchar **data, uchar *data_end)
+{
+ uchar *read_pos= *data;
+ const uint signed_bit= 1 << 15;
+ DBUG_ENTER("set_conversion_functions");
+ /*
+ First execute or types altered by the client, setup the
+ conversion routines for all parameters (one time)
+ */
+ Item_param **it= stmt->param_array;
+ Item_param **end= it + stmt->param_count;
+ THD *thd= stmt->thd;
+ for (; it < end; ++it)
+ {
+ ushort typecode;
+
+ if (read_pos >= data_end)
+ DBUG_RETURN(1);
+
+ typecode= sint2korr(read_pos);
+ read_pos+= 2;
+ (**it).unsigned_flag= MY_TEST(typecode & signed_bit);
+ setup_one_conversion_function(thd, *it, (uchar) (typecode & 0xff));
+ }
+ *data= read_pos;
+ DBUG_RETURN(0);
+}
+
+
static bool setup_conversion_functions(Prepared_statement *stmt,
uchar **data, uchar *data_end,
bool bulk_protocol= 0)
@@ -1012,30 +1042,9 @@ static bool setup_conversion_functions(Prepared_statement *stmt,
if (*read_pos++) //types supplied / first execute
{
- /*
- First execute or types altered by the client, setup the
- conversion routines for all parameters (one time)
- */
- Item_param **it= stmt->param_array;
- Item_param **end= it + stmt->param_count;
- THD *thd= stmt->thd;
- for (; it < end; ++it)
- {
- ushort typecode;
- const uint signed_bit= 1 << 15;
- const uint indicators_bit= 1 << 14;
-
- if (read_pos >= data_end)
- DBUG_RETURN(1);
-
- typecode= sint2korr(read_pos);
- read_pos+= 2;
- (**it).unsigned_flag= MY_TEST(typecode & signed_bit);
- if (bulk_protocol)
- (**it).indicators= MY_TEST(typecode & indicators_bit);
- setup_one_conversion_function(thd, *it,
- (uchar) (typecode & 0xff));
- }
+ *data= read_pos;
+ bool res= set_conversion_functions(stmt, data, data_end);
+ DBUG_RETURN(res);
}
*data= read_pos;
DBUG_RETURN(0);
@@ -2343,7 +2352,7 @@ static bool check_prepared_statement(Prepared_statement *stmt)
/* mysql_test_update returns 2 if we need to switch to multi-update */
if (res != 2)
break;
-
+ /* fall through */
case SQLCOM_UPDATE_MULTI:
res= mysql_test_multiupdate(stmt, tables, res == 2);
break;
@@ -3022,6 +3031,14 @@ static void reset_stmt_params(Prepared_statement *stmt)
}
+static void mysql_stmt_execute_common(THD *thd,
+ ulong stmt_id,
+ uchar *packet,
+ uchar *packet_end,
+ ulong cursor_flags,
+ bool iteration,
+ bool types);
+
/**
COM_STMT_EXECUTE handler: execute a previously prepared statement.
@@ -3044,20 +3061,91 @@ void mysqld_stmt_execute(THD *thd, char *packet_arg, uint packet_length)
uchar *packet= (uchar*)packet_arg; // GCC 4.0.1 workaround
ulong stmt_id= uint4korr(packet);
ulong flags= (ulong) packet[4];
-#ifndef EMBEDDED_LIBRARY
- ulong iterations= uint4korr(packet + 5);
-#else
- ulong iterations= 0; // no support
-#endif
+ uchar *packet_end= packet + packet_length;
+ DBUG_ENTER("mysqld_stmt_execute");
+
+ packet+= 9; /* stmt_id + 5 bytes of flags */
+
+ mysql_stmt_execute_common(thd, stmt_id, packet, packet_end, flags, FALSE,
+ FALSE);
+ DBUG_VOID_RETURN;
+}
+
+
+/**
+ COM_STMT_BULK_EXECUTE handler: execute a previously prepared statement.
+
+ If there are any parameters, then replace parameter markers with the
+ data supplied from the client, and then execute the statement.
+ This function uses binary protocol to send a possible result set
+ to the client.
+
+ @param thd current thread
+ @param packet_arg parameter types and data, if any
+ @param packet_length packet length, including the terminator character.
+
+ @return
+ none: in case of success OK packet or a result set is sent to the
+ client, otherwise an error message is set in THD.
+*/
+
+void mysqld_stmt_bulk_execute(THD *thd, char *packet_arg, uint packet_length)
+{
+ uchar *packet= (uchar*)packet_arg; // GCC 4.0.1 workaround
+ ulong stmt_id= uint4korr(packet);
+ uint flags= (uint) uint2korr(packet + 4);
+ uchar *packet_end= packet + packet_length;
+ DBUG_ENTER("mysqld_stmt_execute_bulk");
+
+ if (!(thd->client_capabilities &
+ MARIADB_CLIENT_STMT_BULK_OPERATIONS))
+ {
+ DBUG_PRINT("error",
+ ("An attempt to execute bulk operation without support"));
+ my_error(ER_UNSUPPORTED_PS, MYF(0));
+ }
+ /* Check for implemented parameters */
+ if (flags & (~STMT_BULK_FLAG_CLIENT_SEND_TYPES))
+ {
+ DBUG_PRINT("error", ("unsupported bulk execute flags %x", flags));
+ my_error(ER_UNSUPPORTED_PS, MYF(0));
+ }
+
+ /* stmt id and two bytes of flags */
+ packet+= 4 + 2;
+ mysql_stmt_execute_common(thd, stmt_id, packet, packet_end, 0, TRUE,
+ (flags & STMT_BULK_FLAG_CLIENT_SEND_TYPES));
+ DBUG_VOID_RETURN;
+}
+
+
+/**
+ Common part of prepared statement execution
+
+ @param thd THD handle
+ @param stmt_id id of the prepared statement
+ @param paket packet with parameters to bind
+ @param packet_end pointer to the byte after parameters end
+ @param cursor_flags cursor flags
+ @param bulk_op id it bulk operation
+ @param read_types flag say that types muast been read
+*/
+
+static void mysql_stmt_execute_common(THD *thd,
+ ulong stmt_id,
+ uchar *packet,
+ uchar *packet_end,
+ ulong cursor_flags,
+ bool bulk_op,
+ bool read_types)
+{
/* Query text for binary, general or slow log, if any of them is open */
String expanded_query;
- uchar *packet_end= packet + packet_length;
Prepared_statement *stmt;
Protocol *save_protocol= thd->protocol;
bool open_cursor;
- DBUG_ENTER("mysqld_stmt_execute");
-
- packet+= 9; /* stmt_id + 5 bytes of flags */
+ DBUG_ENTER("mysqld_stmt_execute_common");
+ DBUG_ASSERT((!read_types) || (read_types && bulk_op));
/* First of all clear possible warnings from the previous command */
thd->reset_for_next_command();
@@ -3069,21 +3157,21 @@ void mysqld_stmt_execute(THD *thd, char *packet_arg, uint packet_length)
llstr(stmt_id, llbuf), "mysqld_stmt_execute");
DBUG_VOID_RETURN;
}
+ stmt->read_types= read_types;
#if defined(ENABLED_PROFILING)
thd->profiling.set_query_source(stmt->query(), stmt->query_length());
#endif
DBUG_PRINT("exec_query", ("%s", stmt->query()));
- DBUG_PRINT("info",("stmt: %p iterations: %lu", stmt, iterations));
+ DBUG_PRINT("info",("stmt: %p bulk_op %d", stmt, bulk_op));
- open_cursor= MY_TEST(flags & (ulong) CURSOR_TYPE_READ_ONLY);
+ open_cursor= MY_TEST(cursor_flags & (ulong) CURSOR_TYPE_READ_ONLY);
thd->protocol= &thd->protocol_binary;
- if (iterations <= 1)
+ if (!bulk_op)
stmt->execute_loop(&expanded_query, open_cursor, packet, packet_end);
else
- stmt->execute_bulk_loop(&expanded_query, open_cursor, packet, packet_end,
- iterations);
+ stmt->execute_bulk_loop(&expanded_query, open_cursor, packet, packet_end);
thd->protocol= save_protocol;
sp_cache_enforce_limit(thd->sp_proc_cache, stored_program_cache_size);
@@ -3426,7 +3514,7 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
{
stmt->state= Query_arena::STMT_ERROR;
stmt->last_errno= thd->get_stmt_da()->sql_errno();
- strncpy(stmt->last_error, thd->get_stmt_da()->message(), MYSQL_ERRMSG_SIZE);
+ strmake_buf(stmt->last_error, thd->get_stmt_da()->message());
}
thd->set_stmt_da(save_stmt_da);
@@ -3590,11 +3678,12 @@ Prepared_statement::Prepared_statement(THD *thd_arg)
cursor(0),
packet(0),
packet_end(0),
- iterations(0),
param_count(0),
last_errno(0),
flags((uint) IS_IN_USE),
+ iterations(0),
start_param(0),
+ read_types(0),
m_sql_mode(thd->variables.sql_mode)
{
init_sql_alloc(&main_mem_root, thd_arg->variables.query_alloc_block_size,
@@ -3631,7 +3720,7 @@ void Prepared_statement::setup_set_params()
set_params_from_actual_params= insert_params_from_actual_params_with_log;
#ifndef EMBEDDED_LIBRARY
set_params= insert_params_with_log;
- set_bulk_params= insert_bulk_params; // TODO: add binlog support
+ set_bulk_params= insert_bulk_params; // RBR is on for bulk operation
#else
//TODO: add bulk support for bulk parameters
set_params_data= emb_insert_params_with_log;
@@ -4013,7 +4102,7 @@ Prepared_statement::execute_loop(String *expanded_query,
Reprepare_observer reprepare_observer;
bool error;
int reprepare_attempt= 0;
- iterations= 0;
+ iterations= FALSE;
/*
- In mysql_sql_stmt_execute() we hide all "external" Items
@@ -4116,11 +4205,11 @@ my_bool bulk_parameters_set(THD *thd)
DBUG_RETURN(FALSE);
}
-ulong bulk_parameters_iterations(THD *thd)
+my_bool bulk_parameters_iterations(THD *thd)
{
Prepared_statement *stmt= (Prepared_statement *) thd->bulk_param;
if (!stmt)
- return 1;
+ return FALSE;
return stmt->bulk_iterations();
}
@@ -4128,7 +4217,8 @@ ulong bulk_parameters_iterations(THD *thd)
my_bool Prepared_statement::set_bulk_parameters(bool reset)
{
DBUG_ENTER("Prepared_statement::set_bulk_parameters");
- DBUG_PRINT("info", ("iteration: %lu", iterations));
+ DBUG_PRINT("info", ("iteration: %d", iterations));
+
if (iterations)
{
#ifndef EMBEDDED_LIBRARY
@@ -4142,31 +4232,24 @@ my_bool Prepared_statement::set_bulk_parameters(bool reset)
reset_stmt_params(this);
DBUG_RETURN(true);
}
- iterations--;
+ if (packet >= packet_end)
+ iterations= FALSE;
}
start_param= 0;
DBUG_RETURN(false);
}
-ulong Prepared_statement::bulk_iterations()
-{
- if (iterations)
- return iterations;
- return start_param ? 1 : 0;
-}
-
bool
Prepared_statement::execute_bulk_loop(String *expanded_query,
bool open_cursor,
uchar *packet_arg,
- uchar *packet_end_arg,
- ulong iterations_arg)
+ uchar *packet_end_arg)
{
Reprepare_observer reprepare_observer;
bool error= 0;
packet= packet_arg;
packet_end= packet_end_arg;
- iterations= iterations_arg;
+ iterations= TRUE;
start_param= true;
#ifndef DBUG_OFF
Item *free_list_state= thd->free_list;
@@ -4180,16 +4263,26 @@ Prepared_statement::execute_bulk_loop(String *expanded_query,
thd->set_bulk_execution(0);
return TRUE;
}
+ /* Check for non zero parameter count*/
+ if (param_count == 0)
+ {
+ DBUG_PRINT("error", ("Statement with no parameters for bulk execution."));
+ my_error(ER_UNSUPPORTED_PS, MYF(0));
+ thd->set_bulk_execution(0);
+ return TRUE;
+ }
if (!(sql_command_flags[lex->sql_command] & CF_SP_BULK_SAFE))
{
+ DBUG_PRINT("error", ("Command is not supported in bulk execution."));
my_error(ER_UNSUPPORTED_PS, MYF(0));
thd->set_bulk_execution(0);
return TRUE;
}
#ifndef EMBEDDED_LIBRARY
- if (setup_conversion_functions(this, &packet, packet_end, TRUE))
+ if (read_types &&
+ set_conversion_functions(this, &packet, packet_end))
#else
// bulk parameters are not supported for embedded, so it will an error
#endif
@@ -4200,6 +4293,7 @@ Prepared_statement::execute_bulk_loop(String *expanded_query,
thd->set_bulk_execution(0);
return true;
}
+ read_types= FALSE;
#ifdef NOT_YET_FROM_MYSQL_5_6
if (unlikely(thd->security_ctx->password_expired &&
diff --git a/sql/sql_prepare.h b/sql/sql_prepare.h
index 820cb43e6d5..203b37b3b26 100644
--- a/sql/sql_prepare.h
+++ b/sql/sql_prepare.h
@@ -72,6 +72,7 @@ private:
void mysqld_stmt_prepare(THD *thd, const char *packet, uint packet_length);
void mysqld_stmt_execute(THD *thd, char *packet, uint packet_length);
+void mysqld_stmt_execute_bulk(THD *thd, char *packet, uint packet_length);
void mysqld_stmt_bulk_execute(THD *thd, char *packet, uint packet_length);
void mysqld_stmt_close(THD *thd, char *packet);
void mysql_sql_stmt_prepare(THD *thd);
@@ -83,7 +84,7 @@ void mysqld_stmt_reset(THD *thd, char *packet);
void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length);
void reinit_stmt_before_use(THD *thd, LEX *lex);
-ulong bulk_parameters_iterations(THD *thd);
+my_bool bulk_parameters_iterations(THD *thd);
my_bool bulk_parameters_set(THD *thd);
/**
Execute a fragment of server code in an isolated context, so that
diff --git a/sql/sql_reload.cc b/sql/sql_reload.cc
index 400c230ea43..c01ad90f5d2 100644
--- a/sql/sql_reload.cc
+++ b/sql/sql_reload.cc
@@ -181,8 +181,12 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options,
slave is not likely to have the same connection names.
*/
tmp_write_to_binlog= 0;
-
- if (!(mi= (get_master_info(&connection_name,
+ if (connection_name.length == 0)
+ {
+ if (master_info_index->flush_all_relay_logs())
+ *write_to_binlog= -1;
+ }
+ else if (!(mi= (get_master_info(&connection_name,
Sql_condition::WARN_LEVEL_ERROR))))
{
result= 1;
@@ -249,7 +253,8 @@ bool reload_acl_and_cache(THD *thd, unsigned long long options,
NOTE: my_error() has been already called by reopen_tables() within
close_cached_tables().
*/
- result= 1;
+ thd->global_read_lock.unlock_global_read_lock(thd);
+ return 1;
}
if (thd->global_read_lock.make_global_read_lock_block_commit(thd)) // Killed
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 98009827cb4..c5fd142f620 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -3912,9 +3912,6 @@ bool mysql_show_binlog_events(THD* thd)
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
- Format_description_log_event *description_event= new
- Format_description_log_event(3); /* MySQL 4.0 by default */
-
DBUG_ASSERT(thd->lex->sql_command == SQLCOM_SHOW_BINLOG_EVENTS ||
thd->lex->sql_command == SQLCOM_SHOW_RELAYLOG_EVENTS);
@@ -3935,6 +3932,9 @@ bool mysql_show_binlog_events(THD* thd)
binary_log= &(mi->rli.relay_log);
}
+ Format_description_log_event *description_event= new
+ Format_description_log_event(3); /* MySQL 4.0 by default */
+
if (binary_log->is_open())
{
SELECT_LEX_UNIT *unit= &thd->lex->unit;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index c6613facde7..15082cdd0c1 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -648,17 +648,15 @@ setup_without_group(THD *thd, Ref_ptr_array ref_pointer_array,
thd->lex->allow_sum_func|= (nesting_map)1 << select->nest_level;
- save_place= thd->lex->current_select->parsing_place;
- thd->lex->current_select->parsing_place= IN_ORDER_BY;
+ save_place= thd->lex->current_select->context_analysis_place;
+ thd->lex->current_select->context_analysis_place= IN_ORDER_BY;
res= res || setup_order(thd, ref_pointer_array, tables, fields, all_fields,
order);
- thd->lex->current_select->parsing_place= save_place;
- thd->lex->allow_sum_func&= ~((nesting_map)1 << select->nest_level);
- save_place= thd->lex->current_select->parsing_place;
- thd->lex->current_select->parsing_place= IN_GROUP_BY;
+ thd->lex->allow_sum_func&= ~((nesting_map)1 << select->nest_level);
+ thd->lex->current_select->context_analysis_place= IN_GROUP_BY;
res= res || setup_group(thd, ref_pointer_array, tables, fields, all_fields,
group, hidden_group_fields);
- thd->lex->current_select->parsing_place= save_place;
+ thd->lex->current_select->context_analysis_place= save_place;
thd->lex->allow_sum_func|= (nesting_map)1 << select->nest_level;
res= res || setup_windows(thd, ref_pointer_array, tables, fields, all_fields,
win_specs, win_funcs);
@@ -712,6 +710,7 @@ JOIN::prepare(TABLE_LIST *tables_init,
if (select_lex->handle_derived(thd->lex, DT_PREPARE))
DBUG_RETURN(1);
+ thd->lex->current_select->context_analysis_place= NO_MATTER;
thd->lex->current_select->is_item_list_lookup= 1;
/*
If we have already executed SELECT, then it have not sense to prevent
@@ -801,12 +800,13 @@ JOIN::prepare(TABLE_LIST *tables_init,
ref_ptrs= ref_ptr_array_slice(0);
- enum_parsing_place save_place= thd->lex->current_select->parsing_place;
- thd->lex->current_select->parsing_place= SELECT_LIST;
+ enum_parsing_place save_place=
+ thd->lex->current_select->context_analysis_place;
+ thd->lex->current_select->context_analysis_place= SELECT_LIST;
if (setup_fields(thd, ref_ptrs, fields_list, MARK_COLUMNS_READ,
&all_fields, 1))
DBUG_RETURN(-1);
- thd->lex->current_select->parsing_place= save_place;
+ thd->lex->current_select->context_analysis_place= save_place;
if (setup_without_group(thd, ref_ptrs, tables_list,
select_lex->leaf_tables, fields_list,
@@ -1991,7 +1991,8 @@ JOIN::optimize_inner()
having= new (thd->mem_root) Item_int(thd, (longlong) 0,1);
zero_result_cause= "Impossible HAVING noticed after reading const tables";
error= 0;
- DBUG_RETURN(0);
+ select_lex->mark_const_derived(zero_result_cause);
+ goto setup_subq_exit;
}
}
@@ -3384,7 +3385,8 @@ void JOIN::exec_inner()
condtions may be arbitrarily costly, and because the optimize phase
might not have produced a complete executable plan for EXPLAINs.
*/
- if (exec_const_cond && !(select_options & SELECT_DESCRIBE) &&
+ if (!zero_result_cause &&
+ exec_const_cond && !(select_options & SELECT_DESCRIBE) &&
!exec_const_cond->val_int())
zero_result_cause= "Impossible WHERE noticed after reading const tables";
@@ -9725,12 +9727,20 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
/*
Step #2: Extract WHERE/ON parts
*/
+ uint i;
+ for (i= join->top_join_tab_count - 1; i >= join->const_tables; i--)
+ {
+ if (!join->join_tab[i].bush_children)
+ break;
+ }
+ uint last_top_base_tab_idx= i;
+
table_map save_used_tables= 0;
used_tables=((select->const_tables=join->const_table_map) |
OUTER_REF_TABLE_BIT | RAND_TABLE_BIT);
JOIN_TAB *tab;
table_map current_map;
- uint i= join->const_tables;
+ i= join->const_tables;
for (tab= first_depth_first_tab(join); tab;
tab= next_depth_first_tab(join, tab), i++)
{
@@ -9769,7 +9779,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
Following force including random expression in last table condition.
It solve problem with select like SELECT * FROM t1 WHERE rand() > 0.5
*/
- if (tab == join->join_tab + join->top_join_tab_count - 1)
+ if (tab == join->join_tab + last_top_base_tab_idx)
current_map|= RAND_TABLE_BIT;
used_tables|=current_map;
@@ -9809,10 +9819,10 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
save_used_tables= 0;
}
else
- {
- tmp= make_cond_for_table(thd, cond, used_tables, current_map, i,
+ {
+ tmp= make_cond_for_table(thd, cond, used_tables, current_map, i,
FALSE, FALSE);
- }
+ }
/* Add conditions added by add_not_null_conds(). */
if (tab->select_cond)
add_cond_and_fix(thd, &tmp, tab->select_cond);
@@ -14517,7 +14527,8 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top,
table->table->maybe_null= FALSE;
table->outer_join= 0;
if (!(straight_join || table->straight))
- table->dep_tables= table->embedding? table->embedding->dep_tables: 0;
+ table->dep_tables= table->embedding && !table->embedding->sj_subq_pred ?
+ table->embedding->dep_tables : 0;
if (table->on_expr)
{
/* Add ON expression to the WHERE or upper-level ON condition. */
@@ -22206,14 +22217,16 @@ int setup_order(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
List<Item> &fields, List<Item> &all_fields, ORDER *order,
bool from_window_spec)
{
- enum_parsing_place parsing_place= thd->lex->current_select->parsing_place;
+ enum_parsing_place context_analysis_place=
+ thd->lex->current_select->context_analysis_place;
thd->where="order clause";
for (; order; order=order->next)
{
if (find_order_in_list(thd, ref_pointer_array, tables, order, fields,
all_fields, FALSE, from_window_spec))
return 1;
- if ((*order->item)->with_window_func && parsing_place != IN_ORDER_BY)
+ if ((*order->item)->with_window_func &&
+ context_analysis_place != IN_ORDER_BY)
{
my_error(ER_WINDOW_FUNCTION_IN_WINDOW_SPEC, MYF(0));
return 1;
@@ -22255,7 +22268,8 @@ setup_group(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
List<Item> &fields, List<Item> &all_fields, ORDER *order,
bool *hidden_group_fields, bool from_window_spec)
{
- enum_parsing_place parsing_place= thd->lex->current_select->parsing_place;
+ enum_parsing_place context_analysis_place=
+ thd->lex->current_select->context_analysis_place;
*hidden_group_fields=0;
ORDER *ord;
@@ -22271,14 +22285,14 @@ setup_group(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
all_fields, TRUE, from_window_spec))
return 1;
(*ord->item)->marker= UNDEF_POS; /* Mark found */
- if ((*ord->item)->with_sum_func && parsing_place == IN_GROUP_BY)
+ if ((*ord->item)->with_sum_func && context_analysis_place == IN_GROUP_BY)
{
my_error(ER_WRONG_GROUP_FIELD, MYF(0), (*ord->item)->full_name());
return 1;
}
if ((*ord->item)->with_window_func)
{
- if (parsing_place == IN_GROUP_BY)
+ if (context_analysis_place == IN_GROUP_BY)
my_error(ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION, MYF(0));
else
my_error(ER_WINDOW_FUNCTION_IN_WINDOW_SPEC, MYF(0));
diff --git a/sql/sql_sequence.cc b/sql/sql_sequence.cc
index 35792bfe72e..be360c59e34 100644
--- a/sql/sql_sequence.cc
+++ b/sql/sql_sequence.cc
@@ -47,18 +47,19 @@ struct Field_definition
static Field_definition sequence_structure[]=
{
- {"next_value", 21, &type_handler_longlong, {STRING_WITH_LEN("next not cached value")},
- FL},
- {"min_value", 21, &type_handler_longlong, {STRING_WITH_LEN("min value")}, FL},
- {"max_value", 21, &type_handler_longlong, {STRING_WITH_LEN("max value")}, FL},
- {"start", 21, &type_handler_longlong, {STRING_WITH_LEN("start value")}, FL},
+ {"next_not_cached_value", 21, &type_handler_longlong,
+ {STRING_WITH_LEN("")}, FL},
+ {"minimum_value", 21, &type_handler_longlong, STRING_WITH_LEN(""), FL},
+ {"maximum_value", 21, &type_handler_longlong, STRING_WITH_LEN(""), FL},
+ {"start_value", 21, &type_handler_longlong, {STRING_WITH_LEN("start value when sequences is created or value if RESTART is used")}, FL},
{"increment", 21, &type_handler_longlong,
{C_STRING_WITH_LEN("increment value")}, FL},
- {"cache", 21, &type_handler_longlong, {STRING_WITH_LEN("cache size")}, FL},
- {"cycle", 1, &type_handler_tiny, {STRING_WITH_LEN("cycle state")},
+ {"cache_size", 21, &type_handler_longlong, STRING_WITH_LEN(""),
+ FL | UNSIGNED_FLAG},
+ {"cycle_option", 1, &type_handler_tiny, {STRING_WITH_LEN("0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed")},
FL | UNSIGNED_FLAG },
- {"round", 21, &type_handler_longlong,
- {STRING_WITH_LEN("How many cycles has been done")}, FL},
+ {"cycle_count", 21, &type_handler_longlong,
+ {STRING_WITH_LEN("How many cycles have been done")}, FL},
{NULL, 0, &type_handler_longlong, {STRING_WITH_LEN("")}, 0}
};
@@ -458,9 +459,12 @@ int SEQUENCE::read_initial_values(TABLE *table_arg)
DBUG_RETURN(error);
}
+
/*
- Read data from sequence table and update values
- Done when table is opened
+ Do the actiual reading of data from sequence table and
+ update values in the sequence object.
+
+ Called once from when table is opened
*/
int SEQUENCE::read_stored_values()
diff --git a/sql/sql_sequence.h b/sql/sql_sequence.h
index b560d03ca52..1dc777657d5 100644
--- a/sql/sql_sequence.h
+++ b/sql/sql_sequence.h
@@ -88,7 +88,8 @@ protected:
class SEQUENCE :public sequence_definition
{
public:
- enum seq_init { SEQ_UNINTIALIZED, SEQ_IN_PREPARE, SEQ_READY_TO_USE };
+ enum seq_init { SEQ_UNINTIALIZED, SEQ_IN_PREPARE, SEQ_IN_ALTER,
+ SEQ_READY_TO_USE };
SEQUENCE();
~SEQUENCE();
int read_initial_values(TABLE *table);
@@ -101,6 +102,7 @@ public:
{
sequence_definition::operator= (*seq);
adjust_values(reserved_until);
+ all_values_used= 0;
}
longlong next_value(TABLE *table, bool second_round, int *error);
bool set_value(TABLE *table, longlong next_value, ulonglong round_arg,
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 1fbd631b754..b2ee8a2eef0 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2015, Oracle and/or its affiliates.
- Copyright (c) 2009, 2016, MariaDB
+ Copyright (c) 2009, 2017, 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
@@ -1095,6 +1095,7 @@ public:
is_handled= FALSE;
break;
}
+ /* fall through */
case ER_COLUMNACCESS_DENIED_ERROR:
case ER_VIEW_NO_EXPLAIN: /* Error was anonymized, ignore all the same. */
case ER_PROCACCESS_DENIED_ERROR:
@@ -1181,8 +1182,8 @@ mysqld_show_create_get_fields(THD *thd, TABLE_LIST *table_list,
else if (thd->lex->table_type == TABLE_TYPE_SEQUENCE &&
table_list->table->s->table_type != TABLE_TYPE_SEQUENCE)
{
- my_error(ER_WRONG_OBJECT, MYF(0),
- table_list->db, table_list->table_name, "SEQUENCE");
+ my_error(ER_NOT_SEQUENCE, MYF(0),
+ table_list->db, table_list->table_name);
goto exit;
}
@@ -4372,7 +4373,8 @@ fill_schema_table_by_open(THD *thd, bool is_show_fields_or_keys,
*/
if (!is_show_fields_or_keys && result &&
(thd->get_stmt_da()->sql_errno() == ER_NO_SUCH_TABLE ||
- thd->get_stmt_da()->sql_errno() == ER_WRONG_OBJECT))
+ thd->get_stmt_da()->sql_errno() == ER_WRONG_OBJECT ||
+ thd->get_stmt_da()->sql_errno() == ER_NOT_SEQUENCE))
{
/*
Hide error for a non-existing table.
@@ -4699,7 +4701,8 @@ static int fill_schema_table_from_frm(THD *thd, TABLE *table,
if (!share)
{
if (thd->get_stmt_da()->sql_errno() == ER_NO_SUCH_TABLE ||
- thd->get_stmt_da()->sql_errno() == ER_WRONG_OBJECT)
+ thd->get_stmt_da()->sql_errno() == ER_WRONG_OBJECT ||
+ thd->get_stmt_da()->sql_errno() == ER_NOT_SEQUENCE)
{
res= 0;
}
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 462b78aeb62..90be57868cd 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -6896,7 +6896,8 @@ bool alter_table_manage_keys(TABLE *table, int indexes_were_disabled,
case Alter_info::LEAVE_AS_IS:
if (!indexes_were_disabled)
break;
- /* fall-through: disabled indexes */
+ /* disabled indexes */
+ /* fall through */
case Alter_info::DISABLE:
error= table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
}
@@ -9002,7 +9003,9 @@ bool mysql_alter_table(THD *thd, const char *new_db, const char *new_name,
TODO don't create the frm in the first place
*/
- deletefrm(alter_ctx.get_tmp_path());
+ const char *path= alter_ctx.get_tmp_path();
+ table->file->ha_create_partitioning_metadata(path, NULL, CHF_DELETE_FLAG);
+ deletefrm(path);
my_free(const_cast<uchar*>(frm.str));
goto end_inplace;
}
@@ -9807,7 +9810,9 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
}
if (to->file->ha_end_bulk_insert() && error <= 0)
{
- to->file->print_error(my_errno,MYF(0));
+ /* Give error, if not already given */
+ if (!thd->is_error())
+ to->file->print_error(my_errno,MYF(0));
error= 1;
}
to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index a0bbf39b138..6ae5a9b91f0 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -4738,9 +4738,11 @@ size_number:
case 'g':
case 'G':
text_shift_number+=10;
+ /* fall through */
case 'm':
case 'M':
text_shift_number+=10;
+ /* fall through */
case 'k':
case 'K':
text_shift_number+=10;
@@ -11970,17 +11972,22 @@ delete_limit_clause:
| LIMIT limit_option ROWS_SYM EXAMINED_SYM { thd->parse_error(); MYSQL_YYABORT; }
;
+opt_plus:
+ /* empty */
+ | '+'
+ ;
+
int_num:
- NUM { int error; $$= (int) my_strtoll10($1.str, (char**) 0, &error); }
+ opt_plus NUM { int error; $$= (int) my_strtoll10($2.str, (char**) 0, &error); }
| '-' NUM { int error; $$= -(int) my_strtoll10($2.str, (char**) 0, &error); }
ulong_num:
- NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
+ opt_plus NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); }
| HEX_NUM { $$= (ulong) strtol($1.str, (char**) 0, 16); }
- | LONG_NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
- | ULONGLONG_NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
- | DECIMAL_NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
- | FLOAT_NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
+ | opt_plus LONG_NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); }
+ | opt_plus ULONGLONG_NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); }
+ | opt_plus DECIMAL_NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); }
+ | opt_plus FLOAT_NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); }
;
real_ulong_num:
@@ -11992,18 +11999,18 @@ real_ulong_num:
;
longlong_num:
- NUM { int error; $$= (longlong) my_strtoll10($1.str, (char**) 0, &error); }
+ opt_plus NUM { int error; $$= (longlong) my_strtoll10($2.str, (char**) 0, &error); }
| LONG_NUM { int error; $$= (longlong) my_strtoll10($1.str, (char**) 0, &error); }
| '-' NUM { int error; $$= -(longlong) my_strtoll10($2.str, (char**) 0, &error); }
| '-' LONG_NUM { int error; $$= -(longlong) my_strtoll10($2.str, (char**) 0, &error); }
ulonglong_num:
- NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
- | ULONGLONG_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
- | LONG_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
- | DECIMAL_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
- | FLOAT_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
+ opt_plus NUM { int error; $$= (ulonglong) my_strtoll10($2.str, (char**) 0, &error); }
+ | opt_plus ULONGLONG_NUM { int error; $$= (ulonglong) my_strtoll10($2.str, (char**) 0, &error); }
+ | opt_plus LONG_NUM { int error; $$= (ulonglong) my_strtoll10($2.str, (char**) 0, &error); }
+ | opt_plus DECIMAL_NUM { int error; $$= (ulonglong) my_strtoll10($2.str, (char**) 0, &error); }
+ | opt_plus FLOAT_NUM { int error; $$= (ulonglong) my_strtoll10($2.str, (char**) 0, &error); }
;
real_ulonglong_num:
diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy
index 3787f34aec4..9cd0944077a 100644
--- a/sql/sql_yacc_ora.yy
+++ b/sql/sql_yacc_ora.yy
@@ -12051,17 +12051,22 @@ delete_limit_clause:
| LIMIT limit_option ROWS_SYM EXAMINED_SYM { thd->parse_error(); MYSQL_YYABORT; }
;
+opt_plus:
+ /* empty */
+ | '+'
+ ;
+
int_num:
- NUM { int error; $$= (int) my_strtoll10($1.str, (char**) 0, &error); }
+ opt_plus NUM { int error; $$= (int) my_strtoll10($2.str, (char**) 0, &error); }
| '-' NUM { int error; $$= -(int) my_strtoll10($2.str, (char**) 0, &error); }
ulong_num:
- NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
+ opt_plus NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); }
| HEX_NUM { $$= (ulong) strtol($1.str, (char**) 0, 16); }
- | LONG_NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
- | ULONGLONG_NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
- | DECIMAL_NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
- | FLOAT_NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); }
+ | opt_plus LONG_NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); }
+ | opt_plus ULONGLONG_NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); }
+ | opt_plus DECIMAL_NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); }
+ | opt_plus FLOAT_NUM { int error; $$= (ulong) my_strtoll10($2.str, (char**) 0, &error); }
;
real_ulong_num:
@@ -12073,18 +12078,18 @@ real_ulong_num:
;
longlong_num:
- NUM { int error; $$= (longlong) my_strtoll10($1.str, (char**) 0, &error); }
+ opt_plus NUM { int error; $$= (longlong) my_strtoll10($2.str, (char**) 0, &error); }
| LONG_NUM { int error; $$= (longlong) my_strtoll10($1.str, (char**) 0, &error); }
| '-' NUM { int error; $$= -(longlong) my_strtoll10($2.str, (char**) 0, &error); }
| '-' LONG_NUM { int error; $$= -(longlong) my_strtoll10($2.str, (char**) 0, &error); }
ulonglong_num:
- NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
- | ULONGLONG_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
- | LONG_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
- | DECIMAL_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
- | FLOAT_NUM { int error; $$= (ulonglong) my_strtoll10($1.str, (char**) 0, &error); }
+ opt_plus NUM { int error; $$= (ulonglong) my_strtoll10($2.str, (char**) 0, &error); }
+ | opt_plus ULONGLONG_NUM { int error; $$= (ulonglong) my_strtoll10($2.str, (char**) 0, &error); }
+ | opt_plus LONG_NUM { int error; $$= (ulonglong) my_strtoll10($2.str, (char**) 0, &error); }
+ | opt_plus DECIMAL_NUM { int error; $$= (ulonglong) my_strtoll10($2.str, (char**) 0, &error); }
+ | opt_plus FLOAT_NUM { int error; $$= (ulonglong) my_strtoll10($2.str, (char**) 0, &error); }
;
real_ulonglong_num:
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index c2a5e183187..28665098d4d 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -1740,7 +1740,10 @@ Sys_var_gtid_binlog_state::do_check(THD *thd, set_var *var)
return true;
}
if (res->length() == 0)
+ {
list= NULL;
+ list_len= 0;
+ }
else if (!(list= gtid_parse_string_to_list(res->ptr(), res->length(),
&list_len)))
{
diff --git a/sql/table.cc b/sql/table.cc
index 9c3613a879c..0a23d2f1f41 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -2056,6 +2056,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
keyinfo= share->key_info;
uint primary_key= my_strcasecmp(system_charset_info, share->keynames.type_names[0],
primary_key_name) ? MAX_KEY : 0;
+ KEY* key_first_info;
if (primary_key >= MAX_KEY && keyinfo->flags & HA_NOSAME)
{
@@ -2135,19 +2136,38 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
keyinfo->name_length+1);
}
+ if (!key)
+ key_first_info= keyinfo;
+
if (ext_key_parts > share->key_parts && key)
{
KEY_PART_INFO *new_key_part= (keyinfo-1)->key_part +
(keyinfo-1)->ext_key_parts;
uint add_keyparts_for_this_key= add_first_key_parts;
+ uint length_bytes= 0, len_null_byte= 0, ext_key_length= 0;
+ Field *field;
/*
Do not extend the key that contains a component
defined over the beginning of a field.
*/
for (i= 0; i < keyinfo->user_defined_key_parts; i++)
- {
+ {
uint fieldnr= keyinfo->key_part[i].fieldnr;
+ field= share->field[keyinfo->key_part[i].fieldnr-1];
+
+ if (field->null_ptr)
+ len_null_byte= HA_KEY_NULL_LENGTH;
+
+ if (field->type() == MYSQL_TYPE_BLOB ||
+ field->real_type() == MYSQL_TYPE_VARCHAR ||
+ field->type() == MYSQL_TYPE_GEOMETRY)
+ {
+ length_bytes= HA_KEY_BLOB_LENGTH;
+ }
+
+ ext_key_length+= keyinfo->key_part[i].length + len_null_byte
+ + length_bytes;
if (share->field[fieldnr-1]->key_length() !=
keyinfo->key_part[i].length)
{
@@ -2156,6 +2176,23 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
}
}
+ if (add_keyparts_for_this_key)
+ {
+ for (i= 0; i < add_keyparts_for_this_key; i++)
+ {
+ uint pk_part_length= key_first_info->key_part[i].store_length;
+ if (keyinfo->ext_key_part_map & 1<<i)
+ {
+ if (ext_key_length + pk_part_length > MAX_KEY_LENGTH)
+ {
+ add_keyparts_for_this_key= i;
+ break;
+ }
+ ext_key_length+= pk_part_length;
+ }
+ }
+ }
+
if (add_keyparts_for_this_key < (keyinfo->ext_key_parts -
keyinfo->user_defined_key_parts))
{
diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc
index 4acf8a3bf1e..f8db20ace99 100644
--- a/sql/wsrep_thd.cc
+++ b/sql/wsrep_thd.cc
@@ -384,7 +384,8 @@ static void wsrep_replication_process(THD *thd)
case WSREP_TRX_MISSING:
/* these suggests a bug in provider code */
WSREP_WARN("bad return from recv() call: %d", rcode);
- /* fall through to node shutdown */
+ /* Shut down this node. */
+ /* fall through */
case WSREP_FATAL:
/* Cluster connectivity is lost.
*