summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2018-08-02 08:19:57 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2018-08-02 08:19:57 +0300
commitef3070e997a6e90c8eadaa833dc47324c2167bb4 (patch)
treecea18cf54188376147d7e4457397c9c663022f27 /sql
parenta90b3862d921ebaeaf3c998cd742e883d2d4af04 (diff)
parent2fb68244b4246221e4f605749913bfe582a4d040 (diff)
downloadmariadb-git-ef3070e997a6e90c8eadaa833dc47324c2167bb4.tar.gz
Merge 10.1 into 10.2
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc8
-rw-r--r--sql/item.cc3
-rw-r--r--sql/item_strfunc.cc112
-rw-r--r--sql/log.cc11
-rw-r--r--sql/mysqld.cc10
-rw-r--r--sql/mysqld.h3
-rw-r--r--sql/opt_subselect.cc69
-rw-r--r--sql/share/CMakeLists.txt12
-rw-r--r--sql/sql_acl.cc13
-rw-r--r--sql/sql_base.cc12
-rw-r--r--sql/sql_parse.cc26
-rw-r--r--sql/sql_select.cc17
-rw-r--r--sql/sql_statistics.cc33
-rw-r--r--sql/sql_statistics.h1
-rw-r--r--sql/sql_table.cc6
-rw-r--r--sql/sql_truncate.cc3
-rw-r--r--sql/sys_vars.cc6
-rw-r--r--sql/table.cc19
-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
23 files changed, 344 insertions, 128 deletions
diff --git a/sql/field.cc b/sql/field.cc
index e84658bb64d..9ca9663f066 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -7978,7 +7978,13 @@ int Field_blob::store(const char *from,uint 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/item.cc b/sql/item.cc
index a501ff6fdc6..58d2b7dbfc0 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
@@ -10408,6 +10408,7 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
if (Field::result_merge_type(real_field_type()) == DECIMAL_RESULT)
{
+ collation.set_numeric();
decimals= MY_MIN(MY_MAX(decimals, item->decimals), DECIMAL_MAX_SCALE);
int item_int_part= item->decimal_int_part();
int item_prec = MY_MAX(prev_decimal_int_part, item_int_part) + decimals;
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 87c766340c7..e332f034fb3 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -1518,32 +1518,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)
- {
- uint 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
- {
- uint 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;
+ uint 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;
}
@@ -1746,7 +1732,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;
@@ -1795,20 +1781,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;
}
}
}
@@ -1820,13 +1817,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
@@ -1841,30 +1841,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 f74e73f47ba..fa1fe3d808c 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -2708,14 +2708,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);
}
}
@@ -2900,7 +2900,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;
@@ -3086,7 +3086,7 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time,
if (! write_error)
{
write_error= 1;
- sql_print_error(ER_THD(thd, ER_ERROR_ON_WRITE), name, tmp_errno);
+ sql_print_error(ER_DEFAULT(ER_ERROR_ON_WRITE), name, tmp_errno);
}
}
}
@@ -8425,8 +8425,7 @@ void MYSQL_BIN_LOG::close(uint exiting)
if (mysql_file_close(index_file.file, MYF(0)) < 0 && ! 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 8dd178108b9..8e2884e2048 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -489,7 +489,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;
@@ -516,6 +516,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;
@@ -5648,6 +5649,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.
@@ -6045,7 +6051,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);
diff --git a/sql/mysqld.h b/sql/mysqld.h
index 5a2dc6dce8d..2604121a9f1 100644
--- a/sql/mysqld.h
+++ b/sql/mysqld.h
@@ -166,7 +166,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/opt_subselect.cc b/sql/opt_subselect.cc
index 36d0116696a..d0be72b8d51 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);
@@ -819,6 +820,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
@@ -1456,6 +1460,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
@@ -1719,6 +1784,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)
{
@@ -3543,7 +3609,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/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 792fe700473..f5c422cc5ea 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
@@ -10937,17 +10937,12 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name,
if (!(combo=(LEX_USER*) thd->alloc(sizeof(st_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 0ac7a112161..36bf39ea8f3 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -6587,6 +6587,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);
@@ -6594,7 +6595,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. */
@@ -6603,7 +6604,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;
}
@@ -6624,7 +6625,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 (;;)
@@ -6657,7 +6658,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;
@@ -6889,7 +6891,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. */
@@ -6934,6 +6935,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_parse.cc b/sql/sql_parse.cc
index 3ec7b54e0a9..dd16200539d 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -724,6 +724,9 @@ void init_update_queries(void)
sql_command_flags[SQLCOM_TRUNCATE]|= CF_FORCE_ORIGINAL_BINLOG_FORMAT;
/* We don't want to replicate DROP for temp tables in row format */
sql_command_flags[SQLCOM_DROP_TABLE]|= 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;
@@ -1577,10 +1580,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;
@@ -7826,36 +7829,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
@@ -7891,6 +7904,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 47ca733468b..643ddfeba39 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -4137,8 +4137,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;
/*
@@ -4305,7 +4305,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,
@@ -8548,8 +8548,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;
}
@@ -9154,7 +9159,6 @@ static bool create_hj_key_for_table(JOIN *join, JOIN_TAB *join_tab,
if (first_keyuse)
{
key_parts++;
- first_keyuse= FALSE;
}
else
{
@@ -9164,7 +9168,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;
}
@@ -9172,6 +9176,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 0743e886eb1..ae72b828ae3 100644
--- a/sql/sql_statistics.cc
+++ b/sql/sql_statistics.cc
@@ -3066,6 +3066,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
diff --git a/sql/sql_statistics.h b/sql/sql_statistics.h
index f46583839d1..0611c021e88 100644
--- a/sql/sql_statistics.h
+++ b/sql/sql_statistics.h
@@ -92,6 +92,7 @@ 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_STRING *db, LEX_STRING *tab);
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 73f62f2f2c8..dbcab9bb870 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -4795,6 +4795,10 @@ int create_table_impl(THD *thd,
{
if (options.or_replace())
{
+ LEX_STRING db_name= {(char *) db, strlen(db)};
+ LEX_STRING tab_name= {(char *) table_name, strlen(table_name)};
+ (void) delete_statistics_for_table(thd, &db_name, &tab_name);
+
TABLE_LIST table_list;
table_list.init_one_table(db, strlen(db), table_name,
strlen(table_name), table_name,
@@ -5326,6 +5330,8 @@ mysql_rename_table(handlerton *base, const char *old_db,
delete file;
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);
else if (error)
my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error);
else if (!(flags & FN_IS_TMP))
diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc
index 8a70e6f6bdb..9a54b4f947f 100644
--- a/sql/sql_truncate.cc
+++ b/sql/sql_truncate.cc
@@ -349,7 +349,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 e6aec472b9e..841e57fa3e2 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -442,6 +442,12 @@ bool check_has_super(sys_var *self, THD *thd, set_var *var)
#endif
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)
{
if (check_has_super(self, thd, var))
diff --git a/sql/table.cc b/sql/table.cc
index 7cb84bcc5ea..6a19b1ebdbc 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -6073,7 +6073,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);
/*
@@ -6122,7 +6122,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 *
@@ -6138,7 +6138,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;
}
@@ -6949,6 +6949,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
*/
@@ -6964,11 +6972,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 be990543757..7dfd1c2ac8e 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. */
@@ -972,6 +973,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 ccd5ed4a86b..82160231b03 100644
--- a/sql/tztime.cc
+++ b/sql/tztime.cc
@@ -1661,7 +1661,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 483da2296ad..672e1d77f47 100644
--- a/sql/wsrep_binlog.cc
+++ b/sql/wsrep_binlog.cc
@@ -318,13 +318,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;
}
@@ -343,6 +358,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);
}
/*
@@ -448,19 +464,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);
Format_description_log_event *ev=NULL;
- 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;
}
@@ -501,6 +532,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 eeb1be72ebb..326b5928366 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -1477,6 +1477,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
@@ -1499,7 +1518,8 @@ static int wsrep_TOI_begin(THD *thd, char *db_, 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:
@@ -1573,8 +1593,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 a504d2eafd3..f4fe6af8d9f 100644
--- a/sql/wsrep_sst.cc
+++ b/sql/wsrep_sst.cc
@@ -193,8 +193,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();
@@ -203,14 +202,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);
}
}
@@ -1366,19 +1369,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);
}
}