summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/CMakeLists.txt28
-rw-r--r--sql/event_data_objects.cc10
-rw-r--r--sql/field.cc8
-rw-r--r--sql/handler.cc2
-rw-r--r--sql/handler.h6
-rw-r--r--sql/item.cc2
-rw-r--r--sql/item.h5
-rw-r--r--sql/item_cmpfunc.h14
-rw-r--r--sql/item_func.h10
-rw-r--r--sql/item_jsonfunc.cc8
-rw-r--r--sql/item_strfunc.cc112
-rw-r--r--sql/log.cc9
-rw-r--r--sql/mysqld.cc12
-rw-r--r--sql/mysqld.h3
-rw-r--r--sql/net_serv.cc2
-rw-r--r--sql/opt_range.cc7
-rw-r--r--sql/opt_split.cc3
-rw-r--r--sql/opt_subselect.cc69
-rw-r--r--sql/semisync_master_ack_receiver.cc3
-rw-r--r--sql/semisync_slave.cc3
-rw-r--r--sql/share/CMakeLists.txt12
-rw-r--r--sql/sql_acl.cc17
-rw-r--r--sql/sql_base.cc12
-rw-r--r--sql/sql_class.h9
-rw-r--r--sql/sql_list.h5
-rw-r--r--sql/sql_parse.cc26
-rw-r--r--sql/sql_select.cc38
-rw-r--r--sql/sql_statistics.cc35
-rw-r--r--sql/sql_statistics.h3
-rw-r--r--sql/sql_table.cc16
-rw-r--r--sql/sql_truncate.cc3
-rw-r--r--sql/sys_vars.cc4
-rw-r--r--sql/table.cc21
-rw-r--r--sql/table_cache.cc2
-rw-r--r--sql/tztime.cc2
-rw-r--r--sql/wsrep_binlog.cc52
-rw-r--r--sql/wsrep_mysqld.cc26
-rw-r--r--sql/wsrep_sst.cc26
-rw-r--r--sql/wsrep_xid.cc5
39 files changed, 416 insertions, 214 deletions
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt
index 0037ff23153..708c36a58b0 100644
--- a/sql/CMakeLists.txt
+++ b/sql/CMakeLists.txt
@@ -203,9 +203,7 @@ IF(MSVC AND NOT WITHOUT_DYNAMIC_PLUGINS)
SET(MYSQLD_LIB ${CMAKE_CURRENT_BINARY_DIR}/mysqld_lib.lib)
SET(MYSQLD_CORELIBS sql mysys dbug strings)
FOREACH (CORELIB ${MYSQLD_CORELIBS})
- GET_TARGET_PROPERTY(LOC ${CORELIB} LOCATION)
- FILE(TO_NATIVE_PATH ${LOC} LOC)
- SET (LIB_LOCATIONS ${LIB_LOCATIONS} ${LOC})
+ SET (LIB_LOCATIONS ${LIB_LOCATIONS} $<TARGET_FILE:${CORELIB}>)
ENDFOREACH (CORELIB)
SET(_PLATFORM x86)
@@ -307,8 +305,7 @@ TARGET_LINK_LIBRARIES(mysqld sql)
# Provide plugins with minimal set of libraries
SET(INTERFACE_LIBS ${LIBRT})
IF(INTERFACE_LIBS)
- SET_TARGET_PROPERTIES(mysqld PROPERTIES LINK_INTERFACE_LIBRARIES
- "${INTERFACE_LIBS}")
+ TARGET_LINK_LIBRARIES(mysqld LINK_PUBLIC ${INTERFACE_LIBS})
ENDIF()
# On Solaris, some extra effort is required in order to get dtrace probes
@@ -421,23 +418,20 @@ SET(DBOPT_FILE ${CMAKE_SOURCE_DIR}/support-files/db.opt )
INSTALL(FILES ${DBOPT_FILE} DESTINATION data/test COMPONENT DataFiles)
# Install initial database on windows
-IF(NOT CMAKE_CROSSCOMPILING)
- GET_TARGET_PROPERTY(MYSQLD_EXECUTABLE mysqld LOCATION)
-ENDIF()
-IF(WIN32 AND MYSQLD_EXECUTABLE)
- CONFIGURE_FILE(
- ${CMAKE_SOURCE_DIR}/cmake/create_initial_db.cmake.in
- ${CMAKE_CURRENT_BINARY_DIR}/create_initial_db.cmake
- @ONLY
- )
-
+IF(WIN32 AND TARGET mysqld AND NOT CMAKE_CROSSCOMPILING)
+
IF(MSVC_IDE OR CMAKE_GENERATOR MATCHES "Xcode")
SET (CONFIG_PARAM -DCONFIG=${CMAKE_CFG_INTDIR})
ENDIF()
MAKE_DIRECTORY(${CMAKE_CURRENT_BINARY_DIR}/data)
ADD_CUSTOM_COMMAND(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/initdb.dep
- COMMAND ${CMAKE_COMMAND} ${CONFIG_PARAM} -P ${CMAKE_CURRENT_BINARY_DIR}/create_initial_db.cmake
+ COMMAND ${CMAKE_COMMAND} ${CONFIG_PARAM}
+ -DTOP_SRCDIR="${CMAKE_SOURCE_DIR}"
+ -DBINDIR="${CMAKE_CURRENT_BINARY_DIR}"
+ -DMYSQLD_EXECUTABLE="$<TARGET_FILE:mysqld>"
+ -DCMAKE_CFG_INTDIR="${CMAKE_CFG_INTDIR}"
+ -P ${CMAKE_SOURCE_DIR}/cmake/create_initial_db.cmake
COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/initdb.dep
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/data
DEPENDS mysqld
@@ -455,7 +449,7 @@ IF(WIN32 AND MYSQLD_EXECUTABLE)
ELSE()
# Not windows or cross compiling, just install an empty directory
INSTALL(FILES ${DUMMY_FILE} DESTINATION data/mysql COMPONENT DataFiles)
-ENDIF(WIN32 AND MYSQLD_EXECUTABLE)
+ENDIF(WIN32 AND TARGET mysqld AND NOT CMAKE_CROSSCOMPILING)
ENDIF(INSTALL_LAYOUT STREQUAL "STANDALONE")
IF(WIN32)
diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc
index 19cb4865ee6..02da3c31c3e 100644
--- a/sql/event_data_objects.cc
+++ b/sql/event_data_objects.cc
@@ -1284,7 +1284,11 @@ Event_job_data::construct_sp_sql(THD *thd, String *sp_sql)
*/
sp_sql->append(STRING_WITH_LEN("() SQL SECURITY INVOKER "));
+ if (thd->variables.sql_mode & MODE_ORACLE)
+ sp_sql->append(STRING_WITH_LEN(" AS BEGIN "));
sp_sql->append(&body);
+ if (thd->variables.sql_mode & MODE_ORACLE)
+ sp_sql->append(STRING_WITH_LEN("; END"));
DBUG_RETURN(thd->is_fatal_error);
}
@@ -1387,9 +1391,6 @@ Event_job_data::execute(THD *thd, bool drop)
goto end;
}
- if (construct_sp_sql(thd, &sp_sql))
- goto end;
-
/*
Set up global thread attributes to reflect the properties of
this Event. We can simply reset these instead of usual
@@ -1401,6 +1402,9 @@ Event_job_data::execute(THD *thd, bool drop)
thd->variables.sql_mode= sql_mode;
thd->variables.time_zone= time_zone;
+ if (construct_sp_sql(thd, &sp_sql))
+ goto end;
+
thd->set_query(sp_sql.c_ptr_safe(), sp_sql.length());
{
diff --git a/sql/field.cc b/sql/field.cc
index e014b62788a..549fc157da9 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -8064,7 +8064,13 @@ int Field_blob::store(const char *from,size_t length,CHARSET_INFO *cs)
return 0;
}
- if (table->blob_storage) // GROUP_CONCAT with ORDER BY | DISTINCT
+ /*
+ For min/max fields of statistical data 'table' is set to NULL.
+ It could not be otherwise as this data is shared by many instances
+ of the same base table.
+ */
+
+ if (table && table->blob_storage) // GROUP_CONCAT with ORDER BY | DISTINCT
{
DBUG_ASSERT(!f_is_hex_escape(flags));
DBUG_ASSERT(field_charset == cs);
diff --git a/sql/handler.cc b/sql/handler.cc
index b3481c7e429..e45607cad66 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -6773,7 +6773,7 @@ int del_global_index_stats_for_table(THD *thd, uchar* cache_key, size_t cache_ke
/* Remove a table from global table statistics */
-int del_global_table_stat(THD *thd, LEX_CSTRING *db, LEX_CSTRING *table)
+int del_global_table_stat(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *table)
{
TABLE_STATS *table_stats;
int res = 0;
diff --git a/sql/handler.h b/sql/handler.h
index 4bcb6438e08..f1080d56bb9 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -2,7 +2,7 @@
#define HANDLER_INCLUDED
/*
Copyright (c) 2000, 2016, Oracle and/or its affiliates.
- Copyright (c) 2009, 2017, MariaDB Corporation.
+ Copyright (c) 2009, 2018, MariaDB
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -818,7 +818,7 @@ struct xid_t {
bqual_length= b;
memcpy(data, d, g+b);
}
- bool is_null() { return formatID == -1; }
+ bool is_null() const { return formatID == -1; }
void null() { formatID= -1; }
my_xid quick_get_my_xid()
{
@@ -4829,5 +4829,5 @@ void print_keydup_error(TABLE *table, KEY *key, const char *msg, myf errflag);
void print_keydup_error(TABLE *table, KEY *key, myf errflag);
int del_global_index_stat(THD *thd, TABLE* table, KEY* key_info);
-int del_global_table_stat(THD *thd, LEX_CSTRING *db, LEX_CSTRING *table);
+int del_global_table_stat(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *table);
#endif /* HANDLER_INCLUDED */
diff --git a/sql/item.cc b/sql/item.cc
index 8782efc88e3..77e751d7789 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2000, 2016, Oracle and/or its affiliates.
+ Copyright (c) 2000, 2018, Oracle and/or its affiliates.
Copyright (c) 2010, 2018, MariaDB Corporation
This program is free software; you can redistribute it and/or modify
diff --git a/sql/item.h b/sql/item.h
index 727d1f33f5f..c013781f30f 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1765,6 +1765,11 @@ public:
virtual bool limit_index_condition_pushdown_processor(void *arg) { return 0; }
virtual bool exists2in_processor(void *arg) { return 0; }
virtual bool find_selective_predicates_list_processor(void *arg) { return 0; }
+ bool cleanup_is_expensive_cache_processor(void *arg)
+ {
+ is_expensive_cache= (int8)(-1);
+ return 0;
+ }
/*
TRUE if the expression depends only on the table indicated by tab_map
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 856aae54a6b..e58644c1699 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -2846,16 +2846,7 @@ public:
bool fix_length_and_dec();
const char *func_name() const { return "regexp"; }
enum precedence precedence() const { return CMP_PRECEDENCE; }
- Item *get_copy(THD *thd)
- { return get_item_copy<Item_func_regex>(thd, this); }
- Item *build_clone(THD *thd)
- {
- Item_func_regex *clone= (Item_func_regex*) Item_bool_func::build_clone(thd);
- if (clone)
- clone->re.reset();
- return clone;
- }
-
+ Item *get_copy(THD *) { return 0; }
void print(String *str, enum_query_type query_type)
{
print_op(str, query_type);
@@ -2895,8 +2886,7 @@ public:
bool fix_fields(THD *thd, Item **ref);
bool fix_length_and_dec();
const char *func_name() const { return "regexp_instr"; }
- Item *get_copy(THD *thd)
- { return get_item_copy<Item_func_regexp_instr>(thd, this); }
+ Item *get_copy(THD *thd) { return 0; }
};
diff --git a/sql/item_func.h b/sql/item_func.h
index 48b2ad2afeb..079775bb971 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -3165,15 +3165,7 @@ public:
{
return TRUE;
}
- Item *get_copy(THD *thd)
- { return get_item_copy<Item_func_sp>(thd, this); }
- Item *build_clone(THD *thd)
- {
- Item_func_sp *clone= (Item_func_sp *) Item_func::build_clone(thd);
- if (clone)
- clone->sp_result_field= NULL;
- return clone;
- }
+ Item *get_copy(THD *) { return 0; }
bool eval_not_null_tables(void *opt_arg)
{
not_null_tables_cache= 0;
diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc
index 5e7f49e2a26..205f2c5d65f 100644
--- a/sql/item_jsonfunc.cc
+++ b/sql/item_jsonfunc.cc
@@ -479,7 +479,7 @@ String *Item_func_json_value::val_str(String *str)
(const uchar *) js->ptr() + js->length());
str->length(0);
- str->set_charset(&my_charset_utf8mb4_bin);
+ str->set_charset(collation.collation);
path.cur_step= path.p.steps;
continue_search:
@@ -2387,8 +2387,9 @@ String *Item_func_json_insert::val_str(String *str)
if ((null_value= args[0]->null_value))
return 0;
- str->set_charset(js->charset());
- json_string_set_cs(&key_name, js->charset());
+ str->set_charset(collation.collation);
+ tmp_js.set_charset(collation.collation);
+ json_string_set_cs(&key_name, collation.collation);
for (n_arg=1, n_path=0; n_arg < arg_count; n_arg+=2, n_path++)
{
@@ -2602,7 +2603,6 @@ continue_point:
json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
(const uchar *) js->ptr() + js->length());
str->length(0);
- str->set_charset(js->charset());
if (json_nice(&je, str, Item_func_json_format::LOOSE))
goto js_error;
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 12618d68c27..50fe1624d48 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -1568,32 +1568,18 @@ String *Item_str_conv::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
String *res;
- if (!(res=args[0]->val_str(str)))
- {
- null_value=1; /* purecov: inspected */
- return 0; /* purecov: inspected */
- }
- null_value=0;
- if (multiply == 1)
- {
- size_t len;
- res= copy_if_not_alloced(&tmp_value, res, res->length());
- len= converter(collation.collation, (char*) res->ptr(), res->length(),
- (char*) res->ptr(), res->length());
- DBUG_ASSERT(len <= res->length());
- res->length(len);
- }
- else
- {
- size_t len= res->length() * multiply;
- tmp_value.alloc(len);
- tmp_value.set_charset(collation.collation);
- len= converter(collation.collation, (char*) res->ptr(), res->length(),
- (char*) tmp_value.ptr(), len);
- tmp_value.length(len);
- res= &tmp_value;
- }
- return res;
+ size_t alloced_length, len;
+
+ if ((null_value= (!(res= args[0]->val_str(&tmp_value)) ||
+ str->alloc((alloced_length= res->length() * multiply)))))
+ return 0;
+
+ len= converter(collation.collation, (char*) res->ptr(), res->length(),
+ (char*) str->ptr(), alloced_length);
+ DBUG_ASSERT(len <= alloced_length);
+ str->set_charset(collation.collation);
+ str->length(len);
+ return str;
}
@@ -1796,7 +1782,7 @@ String *Item_func_substr_index::val_str(String *str)
DBUG_ASSERT(fixed == 1);
char buff[MAX_FIELD_WIDTH];
String tmp(buff,sizeof(buff),system_charset_info);
- String *res= args[0]->val_str(str);
+ String *res= args[0]->val_str(&tmp_value);
String *delimiter= args[1]->val_str(&tmp);
int32 count= (int32) args[2]->val_int();
uint offset;
@@ -1845,20 +1831,31 @@ String *Item_func_substr_index::val_str(String *str)
if (pass == 0) /* count<0 */
{
c+=n+1;
- if (c<=0) return res; /* not found, return original string */
+ if (c<=0)
+ {
+ str->copy(res->ptr(), res->length(), collation.collation);
+ return str; // not found, return the original string
+ }
ptr=res->ptr();
}
else
{
- if (c) return res; /* Not found, return original string */
+ if (c)
+ {
+ str->copy(res->ptr(), res->length(), collation.collation);
+ return str; // not found, return the original string
+ }
if (count>0) /* return left part */
{
- tmp_value.set(*res,0,(ulong) (ptr-res->ptr()));
+ str->copy(res->ptr(), (uint32) (ptr-res->ptr()), collation.collation);
+ return str;
}
else /* return right part */
{
- ptr+= delimiter_length;
- tmp_value.set(*res,(ulong) (ptr-res->ptr()), (ulong) (strend-ptr));
+ ptr+= delimiter_length;
+ str->copy(res->ptr() + (ptr-res->ptr()), (uint32) (strend - ptr),
+ collation.collation);
+ return str;
}
}
}
@@ -1870,13 +1867,16 @@ String *Item_func_substr_index::val_str(String *str)
{ // start counting from the beginning
for (offset=0; ; offset+= delimiter_length)
{
- if ((int) (offset= res->strstr(*delimiter, offset)) < 0)
- return res; // Didn't find, return org string
- if (!--count)
- {
- tmp_value.set(*res,0,offset);
- break;
- }
+ if ((int) (offset= res->strstr(*delimiter, offset)) < 0)
+ {
+ str->copy(res->ptr(), res->length(), collation.collation);
+ return str; // not found, return the original string
+ }
+ if (!--count)
+ {
+ str->copy(res->ptr(), offset, collation.collation);
+ return str;
+ }
}
}
else
@@ -1891,30 +1891,32 @@ String *Item_func_substr_index::val_str(String *str)
address space less than where the found substring is located
in res
*/
- if ((int) (offset= res->strrstr(*delimiter, offset)) < 0)
- return res; // Didn't find, return org string
+ if ((int) (offset= res->strrstr(*delimiter, offset)) < 0)
+ {
+ str->copy(res->ptr(), res->length(), collation.collation);
+ return str; // not found, return the original string
+ }
/*
At this point, we've searched for the substring
the number of times as supplied by the index value
*/
- if (!++count)
- {
- offset+= delimiter_length;
- tmp_value.set(*res,offset,res->length()- offset);
- break;
- }
+ if (!++count)
+ {
+ offset+= delimiter_length;
+ str->copy(res->ptr() + offset, res->length() - offset,
+ collation.collation);
+ return str;
+ }
}
if (count)
- return res; // Didn't find, return org string
+ {
+ str->copy(res->ptr(), res->length(), collation.collation);
+ return str; // not found, return the original string
+ }
}
}
- /*
- We always mark tmp_value as const so that if val_str() is called again
- on this object, we don't disrupt the contents of tmp_value when it was
- derived from another String.
- */
- tmp_value.mark_as_const();
- return (&tmp_value);
+ DBUG_ASSERT(0);
+ return NULL;
}
/*
diff --git a/sql/log.cc b/sql/log.cc
index 6975b58dfb7..93f034543a5 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -2746,14 +2746,14 @@ void MYSQL_LOG::close(uint exiting)
if (log_type == LOG_BIN && mysql_file_sync(log_file.file, MYF(MY_WME)) && ! write_error)
{
write_error= 1;
- sql_print_error(ER_THD_OR_DEFAULT(current_thd, ER_ERROR_ON_WRITE), name, errno);
+ sql_print_error(ER_DEFAULT(ER_ERROR_ON_WRITE), name, errno);
}
if (!(exiting & LOG_CLOSE_DELAYED_CLOSE) &&
mysql_file_close(log_file.file, MYF(MY_WME)) && ! write_error)
{
write_error= 1;
- sql_print_error(ER_THD_OR_DEFAULT(current_thd, ER_ERROR_ON_WRITE), name, errno);
+ sql_print_error(ER_DEFAULT(ER_ERROR_ON_WRITE), name, errno);
}
}
@@ -2937,7 +2937,7 @@ err:
if (!write_error)
{
write_error= 1;
- sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
+ sql_print_error(ER_DEFAULT(ER_ERROR_ON_WRITE), name, errno);
}
mysql_mutex_unlock(&LOCK_log);
return TRUE;
@@ -8474,8 +8474,7 @@ void MYSQL_BIN_LOG::close(uint exiting)
! write_error)
{
write_error= 1;
- sql_print_error(ER_THD_OR_DEFAULT(current_thd, ER_ERROR_ON_WRITE),
- index_file_name, errno);
+ sql_print_error(ER_DEFAULT(ER_ERROR_ON_WRITE), index_file_name, errno);
}
}
log_state= (exiting & LOG_CLOSE_TO_BE_OPENED) ? LOG_TO_BE_OPENED : LOG_CLOSED;
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index ce14dc678c6..31ee89a7cd3 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -484,7 +484,7 @@ my_bool opt_master_verify_checksum= 0;
my_bool opt_slave_sql_verify_checksum= 1;
const char *binlog_format_names[]= {"MIXED", "STATEMENT", "ROW", NullS};
volatile sig_atomic_t calling_initgroups= 0; /**< Used in SIGSEGV handler. */
-uint mysqld_port, test_flags, select_errors, dropping_tables, ha_open_options;
+uint mysqld_port, select_errors, dropping_tables, ha_open_options;
uint mysqld_extra_port;
uint mysqld_port_timeout;
ulong delay_key_write_options;
@@ -512,6 +512,7 @@ ulonglong max_binlog_cache_size=0;
ulong slave_max_allowed_packet= 0;
ulonglong binlog_stmt_cache_size=0;
ulonglong max_binlog_stmt_cache_size=0;
+ulonglong test_flags;
ulonglong query_cache_size=0;
ulong query_cache_limit=0;
ulong executed_events=0;
@@ -5769,6 +5770,11 @@ int win_main(int argc, char **argv)
int mysqld_main(int argc, char **argv)
#endif
{
+#ifndef _WIN32
+ /* We can't close stdin just now, because it may be booststrap mode. */
+ bool please_close_stdin= fcntl(STDIN_FILENO, F_GETFD) >= 0;
+#endif
+
/*
Perform basic thread library and malloc initialization,
to be able to read defaults files and parse options.
@@ -6166,7 +6172,7 @@ int mysqld_main(int argc, char **argv)
#ifndef _WIN32
// try to keep fd=0 busy
- if (!freopen("/dev/null", "r", stdin))
+ if (please_close_stdin && !freopen("/dev/null", "r", stdin))
{
// fall back on failure
fclose(stdin);
@@ -8330,7 +8336,7 @@ my_asn1_time_to_string(const ASN1_TIME *time, char *buf, size_t len)
if (bio == NULL)
return NULL;
- if (!ASN1_TIME_print(bio, time))
+ if (!ASN1_TIME_print(bio, const_cast<ASN1_TIME*>(time)))
goto end;
n_read= BIO_read(bio, buf, (int) (len - 1));
diff --git a/sql/mysqld.h b/sql/mysqld.h
index 4a392eaf196..6c0c7308d91 100644
--- a/sql/mysqld.h
+++ b/sql/mysqld.h
@@ -169,7 +169,8 @@ extern ulong opt_tc_log_size, tc_log_max_pages_used, tc_log_page_size;
extern ulong tc_log_page_waits;
extern my_bool relay_log_purge, opt_innodb_safe_binlog, opt_innodb;
extern my_bool relay_log_recovery;
-extern uint test_flags,select_errors,ha_open_options;
+extern uint select_errors,ha_open_options;
+extern ulonglong test_flags;
extern uint protocol_version, mysqld_port, dropping_tables;
extern ulong delay_key_write_options;
extern char *opt_logname, *opt_slow_logname, *opt_bin_logname,
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index 576ef5009b5..c289fb2bc85 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -110,7 +110,7 @@ void sql_print_error(const char *format,...);
extern, but as it's hard to include sql_priv.h here, we have to
live with this for a while.
*/
-extern uint test_flags;
+extern ulonglong test_flags;
extern ulong bytes_sent, bytes_received, net_big_packet_count;
#ifdef HAVE_QUERY_CACHE
#define USE_QUERY_CACHE
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 6f28ab59c15..107c0d8ed89 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -7628,9 +7628,8 @@ 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_STRUCT(sav_geom_type);
-
- if (field_item->field->type() == MYSQL_TYPE_GEOMETRY)
+ const bool geometry= field_item->field->type() == MYSQL_TYPE_GEOMETRY;
+ if (geometry)
{
sav_geom_type= ((Field_geom*) field_item->field)->geom_type;
/* We have to be able to store all sorts of spatial features here */
@@ -7665,7 +7664,7 @@ SEL_TREE *Item_bool_func::get_full_func_mm_tree(RANGE_OPT_PARAM *param,
}
#ifdef HAVE_SPATIAL
- if (field_item->field->type() == MYSQL_TYPE_GEOMETRY)
+ if (geometry)
{
((Field_geom*) field_item->field)->geom_type= sav_geom_type;
}
diff --git a/sql/opt_split.cc b/sql/opt_split.cc
index 37853bdbbe9..611e70376c8 100644
--- a/sql/opt_split.cc
+++ b/sql/opt_split.cc
@@ -413,7 +413,8 @@ bool JOIN::check_for_splittable_materialized()
for (cand= cand_start; cand < cand_end; cand++)
{
- if (cand->underlying_field->field_index + 1 == fldnr)
+ if (cand->underlying_field->table == table &&
+ cand->underlying_field->field_index + 1 == fldnr)
{
cand->is_usable_for_ref_access= true;
break;
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 06358b3cc20..d1877c6c245 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -441,6 +441,7 @@ bool subquery_types_allow_materialization(Item_in_subselect *in_subs);
static bool replace_where_subcondition(JOIN *, Item **, Item *, Item *, bool);
static int subq_sj_candidate_cmp(Item_in_subselect* el1, Item_in_subselect* el2,
void *arg);
+static void reset_equality_number_for_subq_conds(Item * cond);
static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred);
static bool convert_subq_to_jtbm(JOIN *parent_join,
Item_in_subselect *subq_pred, bool *remove);
@@ -816,6 +817,9 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
details)
* require that compared columns have exactly the same type. This is
a temporary measure to avoid BUG#36752-type problems.
+
+ JOIN_TAB::keyuse_is_valid_for_access_in_chosen_plan expects that for Semi Join Materialization
+ Scan all the items in the select list of the IN Subquery are of the type Item::FIELD_ITEM.
*/
static
@@ -1430,6 +1434,67 @@ static int subq_sj_candidate_cmp(Item_in_subselect* el1, Item_in_subselect* el2,
}
+/**
+ @brief
+ reset the value of the field in_eqaulity_no for all Item_func_eq
+ items in the where clause of the subquery.
+
+ Look for in_equality_no description in Item_func_eq class
+
+ DESCRIPTION
+ Lets have an example:
+ SELECT t1.a FROM t1 WHERE t1.a IN
+ (SELECT t2.a FROM t2 where t2.b IN
+ (select t3.b from t3 where t3.c=27 ))
+
+ So for such a query we have the parent, child and
+ grandchild select.
+
+ So for the equality t2.b = t3.b we set the value for in_equality_no to
+ 0 according to its description. Wewe do the same for t1.a = t2.a.
+ But when we look at the child select (with the grandchild select merged),
+ the query would be
+
+ SELECT t1.a FROM t1 WHERE t1.a IN
+ (SELECT t2.a FROM t2 where t2.b = t3.b and t3.c=27)
+
+ and then when the child select is merged into the parent select the query
+ would look like
+
+ SELECT t1.a FROM t1, semi-join-nest(t2,t3)
+ WHERE t1.a =t2.a and t2.b = t3.b and t3.c=27
+
+ Still we would have in_equality_no set for t2.b = t3.b
+ though it does not take part in the semi-join equality for the parent select,
+ so we should reset its value to UINT_MAX.
+
+ @param cond WHERE clause of the subquery
+*/
+
+static void reset_equality_number_for_subq_conds(Item * cond)
+{
+ if (!cond)
+ return;
+ if (cond->type() == Item::COND_ITEM)
+ {
+ List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
+ Item *item;
+ while ((item=li++))
+ {
+ if (item->type() == Item::FUNC_ITEM &&
+ ((Item_func*)item)->functype()== Item_func::EQ_FUNC)
+ ((Item_func_eq*)item)->in_equality_no= UINT_MAX;
+ }
+ }
+ else
+ {
+ if (cond->type() == Item::FUNC_ITEM &&
+ ((Item_func*)cond)->functype()== Item_func::EQ_FUNC)
+ ((Item_func_eq*)cond)->in_equality_no= UINT_MAX;
+ }
+ return;
+}
+
/*
Convert a subquery predicate into a TABLE_LIST semi-join nest
@@ -1694,6 +1759,7 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
*/
sj_nest->sj_in_exprs= subq_pred->left_expr->cols();
sj_nest->nested_join->sj_outer_expr_list.empty();
+ reset_equality_number_for_subq_conds(sj_nest->sj_on_expr);
if (subq_pred->left_expr->cols() == 1)
{
@@ -3506,7 +3572,8 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
first= tablenr - sjm->tables + 1;
join->best_positions[first].n_sj_tables= sjm->tables;
join->best_positions[first].sj_strategy= SJ_OPT_MATERIALIZE;
- join->sjm_lookup_tables|= s->table->map;
+ for (uint i= first; i < first+ sjm->tables; i++)
+ join->sjm_lookup_tables |= join->best_positions[i].table->table->map;
}
else if (pos->sj_strategy == SJ_OPT_MATERIALIZE_SCAN)
{
diff --git a/sql/semisync_master_ack_receiver.cc b/sql/semisync_master_ack_receiver.cc
index ac17c7de40b..fc36ee35d5d 100644
--- a/sql/semisync_master_ack_receiver.cc
+++ b/sql/semisync_master_ack_receiver.cc
@@ -43,8 +43,7 @@ Ack_receiver::Ack_receiver()
DBUG_ENTER("Ack_receiver::Ack_receiver");
m_status= ST_DOWN;
- mysql_mutex_init(key_LOCK_ack_receiver, &m_mutex,
- MY_MUTEX_INIT_FAST);
+ mysql_mutex_init(key_LOCK_ack_receiver, &m_mutex, NULL);
mysql_cond_init(key_COND_ack_receiver, &m_cond, NULL);
m_pid= 0;
diff --git a/sql/semisync_slave.cc b/sql/semisync_slave.cc
index 86d0176dac1..df8baf045ac 100644
--- a/sql/semisync_slave.cc
+++ b/sql/semisync_slave.cc
@@ -144,8 +144,7 @@ void Repl_semi_sync_slave::kill_connection(MYSQL *mysql)
{
sql_print_information("cannot connect to master to kill slave io_thread's "
"connection");
- if (!ret)
- mysql_close(kill_mysql);
+ mysql_close(kill_mysql);
return;
}
size_t kill_buffer_length = my_snprintf(kill_buffer, 30, "KILL %lu",
diff --git a/sql/share/CMakeLists.txt b/sql/share/CMakeLists.txt
index 1461c57c5c3..2980e6153f5 100644
--- a/sql/share/CMakeLists.txt
+++ b/sql/share/CMakeLists.txt
@@ -45,12 +45,14 @@ SET(files
errmsg-utf8.txt
)
-FOREACH (dir ${dirs})
- INSTALL(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${dir}
- DESTINATION ${INSTALL_MYSQLSHAREDIR} COMPONENT Server)
-ENDFOREACH()
INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/charsets DESTINATION ${INSTALL_MYSQLSHAREDIR}
COMPONENT Common PATTERN "languages.html" EXCLUDE
)
-INSTALL(FILES ${files} DESTINATION ${INSTALL_MYSQLSHAREDIR} COMPONENT Server)
+IF (NOT WITHOUT_SERVER)
+ FOREACH (dir ${dirs})
+ INSTALL(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${dir}
+ DESTINATION ${INSTALL_MYSQLSHAREDIR} COMPONENT Server)
+ ENDFOREACH()
+ INSTALL(FILES ${files} DESTINATION ${INSTALL_MYSQLSHAREDIR} COMPONENT Server)
+ENDIF()
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index d00ee3e07ef..88d1630d94b 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2016, Oracle and/or its affiliates.
+/* Copyright (c) 2000, 2018, Oracle and/or its affiliates.
Copyright (c) 2009, 2018, MariaDB
This program is free software; you can redistribute it and/or modify
@@ -3362,7 +3362,8 @@ int acl_set_default_role(THD *thd, const char *host, const char *user,
ulong query_length= 0;
bool clear_role= FALSE;
char buff[512];
- enum_binlog_format save_binlog_format;
+ enum_binlog_format save_binlog_format=
+ thd->get_current_stmt_binlog_format();
const CSET_STRING query_save __attribute__((unused)) = thd->query_string;
DBUG_ENTER("acl_set_default_role");
@@ -3402,6 +3403,7 @@ int acl_set_default_role(THD *thd, const char *host, const char *user,
if (WSREP(thd) && !IF_WSREP(thd->wsrep_applier, 0))
{
thd->set_query(buff, query_length, system_charset_info);
+ // Attention!!! here is implicit goto error;
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, (char*)"user", NULL);
}
@@ -10984,17 +10986,12 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name,
if (!(combo=(LEX_USER*) thd->alloc(sizeof(LEX_USER))))
DBUG_RETURN(TRUE);
- combo->user.str= sctx->user;
+ combo->user.str= (char *) sctx->priv_user;
mysql_mutex_lock(&acl_cache->lock);
- if ((au= find_user_wild(combo->host.str=(char*)sctx->host_or_ip, combo->user.str)))
- goto found_acl;
- if ((au= find_user_wild(combo->host.str=(char*)sctx->host, combo->user.str)))
- goto found_acl;
- if ((au= find_user_wild(combo->host.str=(char*)sctx->ip, combo->user.str)))
- goto found_acl;
- if ((au= find_user_wild(combo->host.str=(char*)"%", combo->user.str)))
+ if ((au= find_user_wild(combo->host.str= (char *) sctx->priv_host,
+ combo->user.str)))
goto found_acl;
mysql_mutex_unlock(&acl_cache->lock);
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index e46b7675bbe..4f1e149c291 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -6837,6 +6837,7 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join,
Query_arena *arena, backup;
bool result= TRUE;
List<Natural_join_column> *non_join_columns;
+ List<Natural_join_column> *join_columns;
DBUG_ENTER("store_natural_using_join_columns");
DBUG_ASSERT(!natural_using_join->join_columns);
@@ -6844,7 +6845,7 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join,
arena= thd->activate_stmt_arena_if_needed(&backup);
if (!(non_join_columns= new List<Natural_join_column>) ||
- !(natural_using_join->join_columns= new List<Natural_join_column>))
+ !(join_columns= new List<Natural_join_column>))
goto err;
/* Append the columns of the first join operand. */
@@ -6853,7 +6854,7 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join,
nj_col_1= it_1.get_natural_column_ref();
if (nj_col_1->is_common)
{
- natural_using_join->join_columns->push_back(nj_col_1, thd->mem_root);
+ join_columns->push_back(nj_col_1, thd->mem_root);
/* Reset the common columns for the next call to mark_common_columns. */
nj_col_1->is_common= FALSE;
}
@@ -6874,7 +6875,7 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join,
{
const char *using_field_name_ptr= using_field_name->c_ptr();
List_iterator_fast<Natural_join_column>
- it(*(natural_using_join->join_columns));
+ it(*join_columns);
Natural_join_column *common_field;
for (;;)
@@ -6907,7 +6908,8 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join,
}
if (non_join_columns->elements > 0)
- natural_using_join->join_columns->append(non_join_columns);
+ join_columns->append(non_join_columns);
+ natural_using_join->join_columns= join_columns;
natural_using_join->is_join_columns_complete= TRUE;
result= FALSE;
@@ -7139,7 +7141,6 @@ static bool setup_natural_join_row_types(THD *thd,
DBUG_PRINT("info", ("using cached setup_natural_join_row_types"));
DBUG_RETURN(false);
}
- context->select_lex->first_natural_join_processing= false;
List_iterator_fast<TABLE_LIST> table_ref_it(*from_clause);
TABLE_LIST *table_ref; /* Current table reference. */
@@ -7184,6 +7185,7 @@ static bool setup_natural_join_row_types(THD *thd,
change on re-execution
*/
context->natural_join_first_table= context->first_name_resolution_table;
+ context->select_lex->first_natural_join_processing= false;
DBUG_RETURN (false);
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 25e2d736cdc..8dc9dde2b18 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -4036,6 +4036,10 @@ public:
*format= (enum_binlog_format) variables.binlog_format;
*current_format= current_stmt_binlog_format;
}
+ inline enum_binlog_format get_current_stmt_binlog_format()
+ {
+ return current_stmt_binlog_format;
+ }
inline void set_binlog_format(enum_binlog_format format,
enum_binlog_format current_format)
{
@@ -4081,11 +4085,6 @@ public:
DBUG_VOID_RETURN;
}
- inline enum_binlog_format get_current_stmt_binlog_format()
- {
- return current_stmt_binlog_format;
- }
-
inline void set_current_stmt_binlog_format(enum_binlog_format format)
{
current_stmt_binlog_format= format;
diff --git a/sql/sql_list.h b/sql/sql_list.h
index 9f4eaae43f1..27827b42be5 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -278,10 +278,13 @@ public:
*/
inline void swap(base_list &rhs)
{
+ list_node **rhs_last=rhs.last;
swap_variables(list_node *, first, rhs.first);
- swap_variables(list_node **, last, rhs.last);
swap_variables(uint, elements, rhs.elements);
+ rhs.last= last == &first ? &rhs.first : last;
+ last = rhs_last == &rhs.first ? &first : rhs_last;
}
+
inline list_node* last_node() { return *last; }
inline list_node* first_node() { return first;}
inline void *head() { return first->info; }
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 1baa26ab465..49bee1889bd 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -736,6 +736,9 @@ void init_update_queries(void)
/* We don't want to replicate DROP for temp tables in row format */
sql_command_flags[SQLCOM_DROP_TABLE]|= CF_FORCE_ORIGINAL_BINLOG_FORMAT;
sql_command_flags[SQLCOM_DROP_SEQUENCE]|= CF_FORCE_ORIGINAL_BINLOG_FORMAT;
+ /* We don't want to replicate CREATE/DROP INDEX for temp tables in row format */
+ sql_command_flags[SQLCOM_CREATE_INDEX]|= CF_FORCE_ORIGINAL_BINLOG_FORMAT;
+ sql_command_flags[SQLCOM_DROP_INDEX]|= CF_FORCE_ORIGINAL_BINLOG_FORMAT;
/* One can change replication mode with SET */
sql_command_flags[SQLCOM_SET_OPTION]|= CF_FORCE_ORIGINAL_BINLOG_FORMAT;
@@ -1597,10 +1600,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (thd->wsrep_conflict_state == ABORTED &&
command != COM_STMT_CLOSE && command != COM_QUIT)
{
+ mysql_mutex_unlock(&thd->LOCK_thd_data);
my_message(ER_LOCK_DEADLOCK, "Deadlock: wsrep aborted transaction",
MYF(0));
WSREP_DEBUG("Deadlock error for: %s", thd->query());
- mysql_mutex_unlock(&thd->LOCK_thd_data);
thd->reset_killed();
thd->mysys_var->abort = 0;
thd->wsrep_conflict_state = NO_CONFLICT;
@@ -7895,36 +7898,46 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length,
thd->lex->sql_command != SQLCOM_SELECT &&
(thd->wsrep_retry_counter < thd->variables.wsrep_retry_autocommit))
{
- WSREP_DEBUG("wsrep retrying AC query: %s",
+ mysql_mutex_unlock(&thd->LOCK_thd_data);
+ WSREP_DEBUG("wsrep retrying AC query: %s",
(thd->query()) ? thd->query() : "void");
/* Performance Schema Interface instrumentation, end */
MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da());
thd->m_statement_psi= NULL;
thd->m_digest= NULL;
+ // Released thd->LOCK_thd_data above as below could end up
+ // close_thread_tables()/close_open_tables()/close_thread_table()/mysql_mutex_lock(&thd->LOCK_thd_data)
close_thread_tables(thd);
+ mysql_mutex_lock(&thd->LOCK_thd_data);
thd->wsrep_conflict_state= RETRY_AUTOCOMMIT;
thd->wsrep_retry_counter++; // grow
wsrep_copy_query(thd);
thd->set_time();
parser_state->reset(rawbuf, length);
+ mysql_mutex_unlock(&thd->LOCK_thd_data);
}
else
{
- WSREP_DEBUG("%s, thd: %lld is_AC: %d, retry: %lu - %lu SQL: %s",
- (thd->wsrep_conflict_state == ABORTED) ?
+ mysql_mutex_unlock(&thd->LOCK_thd_data);
+ // This does dirty read to wsrep variables but it is only a debug code
+ WSREP_DEBUG("%s, thd: %lld is_AC: %d, retry: %lu - %lu SQL: %s",
+ (thd->wsrep_conflict_state == ABORTED) ?
"BF Aborted" : "cert failure",
(longlong) thd->thread_id, is_autocommit,
- thd->wsrep_retry_counter,
+ thd->wsrep_retry_counter,
thd->variables.wsrep_retry_autocommit, thd->query());
my_message(ER_LOCK_DEADLOCK, "Deadlock: wsrep aborted transaction",
MYF(0));
+
+ mysql_mutex_lock(&thd->LOCK_thd_data);
thd->wsrep_conflict_state= NO_CONFLICT;
if (thd->wsrep_conflict_state != REPLAYING)
thd->wsrep_retry_counter= 0; // reset
+ mysql_mutex_unlock(&thd->LOCK_thd_data);
}
- mysql_mutex_unlock(&thd->LOCK_thd_data);
+
thd->reset_killed();
}
else
@@ -7960,6 +7973,7 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length,
#endif /* WITH_WSREP */
}
+
/*
When you modify mysql_parse(), you may need to modify
mysql_test_parse_for_slave() in this same file.
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index bfd1c7580fc..7a8631a4ac1 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1642,6 +1642,13 @@ JOIN::optimize_inner()
if (optimize_constant_subqueries())
DBUG_RETURN(1);
+ if (conds && conds->with_subquery())
+ (void) conds->walk(&Item::cleanup_is_expensive_cache_processor,
+ 0, (void *) 0);
+ if (having && having->with_subquery())
+ (void) having->walk(&Item::cleanup_is_expensive_cache_processor,
+ 0, (void *) 0);
+
List<Item> eq_list;
if (setup_degenerate_jtbm_semi_joins(this, join_list, eq_list))
@@ -1687,6 +1694,13 @@ JOIN::optimize_inner()
conds= optimize_cond(this, conds, join_list, FALSE,
&cond_value, &cond_equal, OPT_LINK_EQUAL_FIELDS);
+ if (thd->is_error())
+ {
+ error= 1;
+ DBUG_PRINT("error",("Error from optimize_cond"));
+ DBUG_RETURN(1);
+ }
+
if (thd->lex->sql_command == SQLCOM_SELECT &&
optimizer_flag(thd, OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY))
{
@@ -1752,13 +1766,6 @@ JOIN::optimize_inner()
DBUG_RETURN(1);
}
- if (unlikely(thd->is_error()))
- {
- error= 1;
- DBUG_PRINT("error",("Error from optimize_cond"));
- DBUG_RETURN(1);
- }
-
{
having= optimize_cond(this, having, join_list, TRUE,
&having_value, &having_equal);
@@ -4618,8 +4625,8 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
int ref_changed;
do
{
- more_const_tables_found:
ref_changed = 0;
+ more_const_tables_found:
found_ref=0;
/*
@@ -4788,7 +4795,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
}
}
}
- } while (join->const_table_map & found_ref && ref_changed);
+ } while (ref_changed);
join->sort_by_table= get_sort_by_table(join->order, join->group_list,
join->select_lex->leaf_tables,
@@ -9025,8 +9032,13 @@ bool JOIN_TAB::keyuse_is_valid_for_access_in_chosen_plan(JOIN *join,
st_select_lex *sjm_sel= emb_sj_nest->sj_subq_pred->unit->first_select();
for (uint i= 0; i < sjm_sel->item_list.elements; i++)
{
- if (sjm_sel->ref_pointer_array[i] == keyuse->val)
- return true;
+ DBUG_ASSERT(sjm_sel->ref_pointer_array[i]->real_item()->type() == Item::FIELD_ITEM);
+ if (keyuse->val->real_item()->type() == Item::FIELD_ITEM)
+ {
+ Field *field = ((Item_field*)sjm_sel->ref_pointer_array[i]->real_item())->field;
+ if (field->eq(((Item_field*)keyuse->val->real_item())->field))
+ return true;
+ }
}
return false;
}
@@ -9674,7 +9686,6 @@ static bool create_hj_key_for_table(JOIN *join, JOIN_TAB *join_tab,
if (first_keyuse)
{
key_parts++;
- first_keyuse= FALSE;
}
else
{
@@ -9684,7 +9695,7 @@ static bool create_hj_key_for_table(JOIN *join, JOIN_TAB *join_tab,
if (curr->keypart == keyuse->keypart &&
!(~used_tables & curr->used_tables) &&
join_tab->keyuse_is_valid_for_access_in_chosen_plan(join,
- keyuse) &&
+ curr) &&
are_tables_local(join_tab, curr->used_tables))
break;
}
@@ -9692,6 +9703,7 @@ static bool create_hj_key_for_table(JOIN *join, JOIN_TAB *join_tab,
key_parts++;
}
}
+ first_keyuse= FALSE;
keyuse++;
} while (keyuse->table == table && keyuse->is_for_hash_join());
if (!key_parts)
diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc
index 00ed7fb0202..ea18484f8a4 100644
--- a/sql/sql_statistics.cc
+++ b/sql/sql_statistics.cc
@@ -3060,6 +3060,39 @@ int read_statistics_for_table(THD *thd, TABLE *table, TABLE_LIST *stat_tables)
/**
+ @breif
+ Cleanup of min/max statistical values for table share
+*/
+
+void delete_stat_values_for_table_share(TABLE_SHARE *table_share)
+{
+ TABLE_STATISTICS_CB *stats_cb= &table_share->stats_cb;
+ Table_statistics *table_stats= stats_cb->table_stats;
+ if (!table_stats)
+ return;
+ Column_statistics *column_stats= table_stats->column_stats;
+ if (!column_stats)
+ return;
+
+ for (Field **field_ptr= table_share->field;
+ *field_ptr;
+ field_ptr++, column_stats++)
+ {
+ if (column_stats->min_value)
+ {
+ delete column_stats->min_value;
+ column_stats->min_value= NULL;
+ }
+ if (column_stats->max_value)
+ {
+ delete column_stats->max_value;
+ column_stats->max_value= NULL;
+ }
+ }
+}
+
+
+/**
@brief
Check whether any statistics is to be read for tables from a table list
@@ -3289,7 +3322,7 @@ int read_statistics_for_tables_if_needed(THD *thd, TABLE_LIST *tables)
The function is called when executing the statement DROP TABLE 'tab'.
*/
-int delete_statistics_for_table(THD *thd, LEX_CSTRING *db, LEX_CSTRING *tab)
+int delete_statistics_for_table(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *tab)
{
int err;
enum_binlog_format save_binlog_format;
diff --git a/sql/sql_statistics.h b/sql/sql_statistics.h
index 7ec742b70db..c2700eaee41 100644
--- a/sql/sql_statistics.h
+++ b/sql/sql_statistics.h
@@ -92,9 +92,10 @@ int read_statistics_for_tables_if_needed(THD *thd, TABLE_LIST *tables);
int collect_statistics_for_table(THD *thd, TABLE *table);
int alloc_statistics_for_table_share(THD* thd, TABLE_SHARE *share,
bool is_safe);
+void delete_stat_values_for_table_share(TABLE_SHARE *table_share);
int alloc_statistics_for_table(THD *thd, TABLE *table);
int update_statistics_for_table(THD *thd, TABLE *table);
-int delete_statistics_for_table(THD *thd, LEX_CSTRING *db, LEX_CSTRING *tab);
+int delete_statistics_for_table(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *tab);
int delete_statistics_for_column(THD *thd, TABLE *tab, Field *col);
int delete_statistics_for_index(THD *thd, TABLE *tab, KEY *key_info,
bool ext_prefixes_only);
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 08e1c1c69d3..92fcba4972f 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -4860,6 +4860,8 @@ int create_table_impl(THD *thd,
{
if (options.or_replace())
{
+ (void) delete_statistics_for_table(thd, db, table_name);
+
TABLE_LIST table_list;
table_list.init_one_table(db, table_name, 0, TL_WRITE_ALLOW_WRITE);
table_list.table= create_info->table;
@@ -5483,13 +5485,13 @@ mysql_rename_table(handlerton *base, const LEX_CSTRING *old_db,
}
delete file;
- if (unlikely(error))
- {
- if (error == HA_ERR_WRONG_COMMAND)
- my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER TABLE");
- else
- my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error);
- }
+ if (error == HA_ERR_WRONG_COMMAND)
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER TABLE");
+ else if (error == ENOTDIR)
+ my_error(ER_BAD_DB_ERROR, MYF(0), new_db->str);
+ else if (error)
+ my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error);
+
else if (!(flags & FN_IS_TMP))
mysql_audit_rename_table(thd, old_db, old_name, new_db, new_name);
diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc
index d515aacd1d0..34177242704 100644
--- a/sql/sql_truncate.cc
+++ b/sql/sql_truncate.cc
@@ -350,7 +350,8 @@ bool Sql_cmd_truncate_table::lock_table(THD *thd, TABLE_LIST *table_ref,
{
DEBUG_SYNC(thd, "upgrade_lock_for_truncate");
/* To remove the table from the cache we need an exclusive lock. */
- if (wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_DROP))
+ if (wait_while_table_is_used(thd, table,
+ *hton_can_recreate ? HA_EXTRA_PREPARE_FOR_DROP : HA_EXTRA_NOT_USED))
DBUG_RETURN(TRUE);
m_ticket_downgrade= table->mdl_ticket;
/* Close if table is going to be recreated. */
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 75a962939ae..6f65b960132 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -471,6 +471,10 @@ bool check_has_super(sys_var *self, THD *thd, set_var *var)
return false;
}
+static Sys_var_bit Sys_core_file("core_file", "write a core-file on crashes",
+ READ_ONLY GLOBAL_VAR(test_flags), NO_CMD_LINE,
+ TEST_CORE_ON_SIGNAL, DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG,
+ 0,0,0);
static bool binlog_format_check(sys_var *self, THD *thd, set_var *var)
{
diff --git a/sql/table.cc b/sql/table.cc
index e98836cd93c..5b6ed0921e3 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -2183,7 +2183,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;
+ KEY* key_first_info= NULL;
if (primary_key >= MAX_KEY && keyinfo->flags & HA_NOSAME)
{
@@ -6207,7 +6207,7 @@ Field_iterator_table_ref::get_or_create_column_ref(THD *thd, TABLE_LIST *parent_
nj_col= natural_join_it.column_ref();
DBUG_ASSERT(nj_col);
}
- DBUG_ASSERT(!nj_col->table_field ||
+ DBUG_ASSERT(!nj_col->table_field || !nj_col->table_field->field ||
nj_col->table_ref->table == nj_col->table_field->field->table);
/*
@@ -6256,7 +6256,7 @@ Field_iterator_table_ref::get_or_create_column_ref(THD *thd, TABLE_LIST *parent_
RETURN
# Pointer to a column of a natural join (or its operand)
- NULL No memory to allocate the column
+ NULL We didn't originally have memory to allocate the column
*/
Natural_join_column *
@@ -6272,7 +6272,7 @@ Field_iterator_table_ref::get_natural_column_ref()
*/
nj_col= natural_join_it.column_ref();
DBUG_ASSERT(nj_col &&
- (!nj_col->table_field ||
+ (!nj_col->table_field || !nj_col->table_field->field ||
nj_col->table_ref->table == nj_col->table_field->field->table));
return nj_col;
}
@@ -7096,6 +7096,14 @@ void TABLE::create_key_part_by_field(KEY_PART_INFO *key_part_info,
The function checks whether a possible key satisfies the constraints
imposed on the keys of any temporary table.
+ We need to filter out BLOB columns here, because ref access optimizer creates
+ KEYUSE objects for equalities for non-key columns for two puproses:
+ 1. To discover possible keys for derived_with_keys optimization
+ 2. To do hash joins
+ For the purpose of #1, KEYUSE objects are not created for "blob_column=..." .
+ However, they might be created for #2. In order to catch that case, we filter
+ them out here.
+
@return TRUE if the key is valid
@return FALSE otherwise
*/
@@ -7111,11 +7119,12 @@ bool TABLE::check_tmp_key(uint key, uint key_parts,
{
uint fld_idx= next_field_no(arg);
reg_field= field + fld_idx;
+ if ((*reg_field)->type() == MYSQL_TYPE_BLOB)
+ return FALSE;
uint fld_store_len= (uint16) (*reg_field)->key_length();
if ((*reg_field)->real_maybe_null())
fld_store_len+= HA_KEY_NULL_LENGTH;
- if ((*reg_field)->type() == MYSQL_TYPE_BLOB ||
- (*reg_field)->real_type() == MYSQL_TYPE_VARCHAR ||
+ if ((*reg_field)->real_type() == MYSQL_TYPE_VARCHAR ||
(*reg_field)->type() == MYSQL_TYPE_GEOMETRY)
fld_store_len+= HA_KEY_BLOB_LENGTH;
key_len+= fld_store_len;
diff --git a/sql/table_cache.cc b/sql/table_cache.cc
index a26a62bcfde..e82bb13228b 100644
--- a/sql/table_cache.cc
+++ b/sql/table_cache.cc
@@ -50,6 +50,7 @@
#include "lf.h"
#include "table.h"
#include "sql_base.h"
+#include "sql_statistics.h"
/** Configuration. */
@@ -991,6 +992,7 @@ void tdc_release_share(TABLE_SHARE *share)
}
if (share->tdc->flushed || tdc_records() > tdc_size)
{
+ delete_stat_values_for_table_share(share);
mysql_mutex_unlock(&LOCK_unused_shares);
tdc_delete_share_from_hash(share->tdc);
DBUG_VOID_RETURN;
diff --git a/sql/tztime.cc b/sql/tztime.cc
index 61fbee1731a..177521e5a55 100644
--- a/sql/tztime.cc
+++ b/sql/tztime.cc
@@ -1653,7 +1653,7 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
{
/* If we are in bootstrap mode we should not load time zone tables */
return_val= time_zone_tables_exist= 0;
- goto end_with_setting_default_tz;
+ goto end_with_cleanup;
}
/*
diff --git a/sql/wsrep_binlog.cc b/sql/wsrep_binlog.cc
index cafd41b2653..0cbcdcd64aa 100644
--- a/sql/wsrep_binlog.cc
+++ b/sql/wsrep_binlog.cc
@@ -322,13 +322,28 @@ int wsrep_write_cache(wsrep_t* const wsrep,
void wsrep_dump_rbr_buf(THD *thd, const void* rbr_buf, size_t buf_len)
{
- char filename[PATH_MAX]= {0};
- int len= snprintf(filename, PATH_MAX, "%s/GRA_%lld_%lld.log",
+ int len= snprintf(NULL, 0, "%s/GRA_%lld_%lld.log",
wsrep_data_home_dir, (longlong) thd->thread_id,
(longlong) wsrep_thd_trx_seqno(thd));
- if (len >= PATH_MAX)
+ if (len < 0)
{
- WSREP_ERROR("RBR dump path too long: %d, skipping dump.", len);
+ WSREP_ERROR("snprintf error: %d, skipping dump.", len);
+ return;
+ }
+ /*
+ len doesn't count the \0 end-of-string. Use len+1 below
+ to alloc and pass as an argument to snprintf.
+ */
+
+ char *filename= (char *)malloc(len+1);
+ int len1= snprintf(filename, len+1, "%s/GRA_%lld_%lld.log",
+ wsrep_data_home_dir, (longlong) thd->thread_id,
+ (long long)wsrep_thd_trx_seqno(thd));
+
+ if (len > len1)
+ {
+ WSREP_ERROR("RBR dump path truncated: %d, skipping dump.", len);
+ free(filename);
return;
}
@@ -347,6 +362,7 @@ void wsrep_dump_rbr_buf(THD *thd, const void* rbr_buf, size_t buf_len)
WSREP_ERROR("Failed to open file '%s': %d (%s)",
filename, errno, strerror(errno));
}
+ free(filename);
}
/*
@@ -452,19 +468,34 @@ void wsrep_dump_rbr_buf_with_header(THD *thd, const void *rbr_buf,
{
DBUG_ENTER("wsrep_dump_rbr_buf_with_header");
- char filename[PATH_MAX]= {0};
File file;
IO_CACHE cache;
Log_event_writer writer(&cache, 0);
Format_description_log_event *ev= 0;
- int len= my_snprintf(filename, PATH_MAX, "%s/GRA_%lld_%lld_v2.log",
- wsrep_data_home_dir, (longlong) thd->thread_id,
- (long long) wsrep_thd_trx_seqno(thd));
+ longlong thd_trx_seqno= (long long)wsrep_thd_trx_seqno(thd);
+ int len= snprintf(NULL, 0, "%s/GRA_%lld_%lld_v2.log",
+ wsrep_data_home_dir, (longlong)thd->thread_id,
+ thd_trx_seqno);
+ /*
+ len doesn't count the \0 end-of-string. Use len+1 below
+ to alloc and pass as an argument to snprintf.
+ */
+ char *filename;
+ if (len < 0 || !(filename= (char*)malloc(len+1)))
+ {
+ WSREP_ERROR("snprintf error: %d, skipping dump.", len);
+ DBUG_VOID_RETURN;
+ }
+
+ int len1= snprintf(filename, len+1, "%s/GRA_%lld_%lld_v2.log",
+ wsrep_data_home_dir, (longlong) thd->thread_id,
+ thd_trx_seqno);
- if (len >= PATH_MAX)
+ if (len > len1)
{
- WSREP_ERROR("RBR dump path too long: %d, skipping dump.", len);
+ WSREP_ERROR("RBR dump path truncated: %d, skipping dump.", len);
+ free(filename);
DBUG_VOID_RETURN;
}
@@ -505,6 +536,7 @@ cleanup2:
end_io_cache(&cache);
cleanup1:
+ free(filename);
mysql_file_close(file, MYF(MY_WME));
if (!thd->wsrep_applier) delete ev;
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc
index 0a2735fe0b7..667fdb779ea 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -1480,6 +1480,25 @@ static bool wsrep_can_run_in_toi(THD *thd, const char *db, const char *table,
}
}
+static const char* wsrep_get_query_or_msg(const THD* thd)
+{
+ switch(thd->lex->sql_command)
+ {
+ case SQLCOM_CREATE_USER:
+ return "CREATE USER";
+ case SQLCOM_GRANT:
+ return "GRANT";
+ case SQLCOM_REVOKE:
+ return "REVOKE";
+ case SQLCOM_SET_OPTION:
+ if (thd->lex->definer)
+ return "SET PASSWORD";
+ /* fallthrough */
+ default:
+ return thd->query();
+ }
+}
+
/*
returns:
0: statement was replicated as TOI
@@ -1502,7 +1521,8 @@ static int wsrep_TOI_begin(THD *thd, const char *db_, const char *table_,
}
WSREP_DEBUG("TO BEGIN: %lld, %d : %s", (long long)wsrep_thd_trx_seqno(thd),
- thd->wsrep_exec_mode, thd->query() );
+ thd->wsrep_exec_mode, wsrep_get_query_or_msg(thd));
+
switch (thd->lex->sql_command)
{
case SQLCOM_CREATE_VIEW:
@@ -1576,8 +1596,8 @@ static void wsrep_TOI_end(THD *thd) {
wsrep_status_t ret;
wsrep_to_isolation--;
- WSREP_DEBUG("TO END: %lld, %d : %s", (long long)wsrep_thd_trx_seqno(thd),
- thd->wsrep_exec_mode, (thd->query()) ? thd->query() : "void");
+ WSREP_DEBUG("TO END: %lld, %d: %s", (long long)wsrep_thd_trx_seqno(thd),
+ thd->wsrep_exec_mode, wsrep_get_query_or_msg(thd));
wsrep_set_SE_checkpoint(thd->wsrep_trx_meta.gtid.uuid,
thd->wsrep_trx_meta.gtid.seqno);
diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc
index d5b0344c456..8816a31330e 100644
--- a/sql/wsrep_sst.cc
+++ b/sql/wsrep_sst.cc
@@ -192,8 +192,7 @@ void wsrep_sst_grab ()
// Wait for end of SST
bool wsrep_sst_wait ()
{
- struct timespec wtime = {WSREP_TIMEDWAIT_SECONDS, 0};
- uint32 total_wtime = 0;
+ double total_wtime = 0;
if (mysql_mutex_lock (&LOCK_wsrep_sst))
abort();
@@ -202,14 +201,18 @@ bool wsrep_sst_wait ()
while (!sst_complete)
{
+ struct timespec wtime;
+ set_timespec(wtime, WSREP_TIMEDWAIT_SECONDS);
+ time_t start_time = time(NULL);
mysql_cond_timedwait (&COND_wsrep_sst, &LOCK_wsrep_sst, &wtime);
+ time_t end_time = time(NULL);
if (!sst_complete)
{
- total_wtime += wtime.tv_sec;
- WSREP_DEBUG("Waiting for SST to complete. waited %u secs.", total_wtime);
+ total_wtime += difftime(end_time, start_time);
+ WSREP_DEBUG("Waiting for SST to complete. current seqno: %ld waited %f secs.", local_seqno, total_wtime);
service_manager_extend_timeout(WSREP_EXTEND_TIMEOUT_INTERVAL,
- "WSREP state transfer ongoing, current seqno: %ld", local_seqno);
+ "WSREP state transfer ongoing, current seqno: %ld waited %f secs", local_seqno, total_wtime);
}
}
@@ -1365,19 +1368,22 @@ void wsrep_SE_init_grab()
void wsrep_SE_init_wait()
{
- struct timespec wtime = {WSREP_TIMEDWAIT_SECONDS, 0};
- uint32 total_wtime=0;
+ double total_wtime=0;
while (SE_initialized == false)
{
+ struct timespec wtime;
+ set_timespec(wtime, WSREP_TIMEDWAIT_SECONDS);
+ time_t start_time = time(NULL);
mysql_cond_timedwait (&COND_wsrep_sst_init, &LOCK_wsrep_sst_init, &wtime);
+ time_t end_time = time(NULL);
if (!SE_initialized)
{
- total_wtime += wtime.tv_sec;
- WSREP_DEBUG("Waiting for SST to complete. waited %u secs.", total_wtime);
+ total_wtime += difftime(end_time, start_time);
+ WSREP_DEBUG("Waiting for SST to complete. current seqno: %ld waited %f secs.", local_seqno, total_wtime);
service_manager_extend_timeout(WSREP_EXTEND_TIMEOUT_INTERVAL,
- "WSREP SE initialization ongoing.");
+ "WSREP state transfer ongoing, current seqno: %ld waited %f secs", local_seqno, total_wtime);
}
}
diff --git a/sql/wsrep_xid.cc b/sql/wsrep_xid.cc
index 618c98eade7..2834100568a 100644
--- a/sql/wsrep_xid.cc
+++ b/sql/wsrep_xid.cc
@@ -156,15 +156,14 @@ bool wsrep_get_SE_checkpoint(wsrep_uuid_t& uuid, wsrep_seqno_t& seqno)
seqno= WSREP_SEQNO_UNDEFINED;
XID xid;
- memset(&xid, 0, sizeof(xid));
- xid.formatID= -1;
+ xid.null();
if (wsrep_get_SE_checkpoint(xid))
{
return true;
}
- if (xid.formatID == -1) // nil XID
+ if (xid.is_null())
{
return false;
}