summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2021-02-23 13:01:27 +0100
committerSergei Golubchik <serg@mariadb.org>2021-02-23 13:06:22 +0100
commitf33e57a9e66f7e1790cb84b141381bb668e281a0 (patch)
tree31bb1c5bd8e0addc9e994a1bb42b4703c37f7ed8 /sql
parent1a0526e2f294acdcac829672794ee1fe708eb2b3 (diff)
parent245d33db4e0586df4fe28362fb002cef0151a1c9 (diff)
downloadmariadb-git-f33e57a9e66f7e1790cb84b141381bb668e281a0.tar.gz
Merge branch '10.4' into 10.5
Diffstat (limited to 'sql')
-rw-r--r--sql/item.cc5
-rw-r--r--sql/item_subselect.cc28
-rw-r--r--sql/item_subselect.h3
-rw-r--r--sql/lock.cc17
-rw-r--r--sql/log.cc5
-rw-r--r--sql/signal_handler.cc3
-rw-r--r--sql/sql_acl.cc42
-rw-r--r--sql/sql_admin.cc4
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_select.cc33
-rw-r--r--sql/sql_show.cc10
-rw-r--r--sql/sql_statistics.cc93
-rw-r--r--sql/sql_statistics.h11
-rw-r--r--sql/sql_truncate.cc23
-rw-r--r--sql/sql_tvc.cc27
-rw-r--r--sql/sql_update.cc18
-rw-r--r--sql/structs.h2
-rw-r--r--sql/table.cc4
-rw-r--r--sql/table.h2
-rw-r--r--sql/wsrep_mysqld.cc17
-rw-r--r--sql/wsrep_mysqld.h2
-rw-r--r--sql/wsrep_sst.cc62
-rw-r--r--sql/wsrep_var.cc20
23 files changed, 293 insertions, 140 deletions
diff --git a/sql/item.cc b/sql/item.cc
index a21bd490272..f818a9f02e7 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -9370,8 +9370,9 @@ bool Item_default_value::fix_fields(THD *thd, Item **items)
memcpy((void *)def_field, (void *)field_arg->field,
field_arg->field->size_of());
def_field->reset_fields();
- // If non-constant default value expression
- if (def_field->default_value && def_field->default_value->flags)
+ // If non-constant default value expression or a blob
+ if (def_field->default_value &&
+ (def_field->default_value->flags || def_field->flags & BLOB_FLAG))
{
uchar *newptr= (uchar*) thd->alloc(1+def_field->pack_length());
if (!newptr)
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 7916bcb45a9..76dbe06c50e 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -278,7 +278,11 @@ bool Item_subselect::fix_fields(THD *thd_param, Item **ref)
{
if (sl->tvc)
{
- wrap_tvc_into_select(thd, sl);
+ if (!(sl= wrap_tvc_into_select(thd, sl)))
+ {
+ res= TRUE;
+ goto end;
+ }
}
}
@@ -382,7 +386,7 @@ bool Item_subselect::mark_as_eliminated_processor(void *arg)
bool Item_subselect::eliminate_subselect_processor(void *arg)
{
unit->item= NULL;
- unit->exclude_from_tree();
+ unit->exclude();
eliminated= TRUE;
return FALSE;
}
@@ -451,6 +455,26 @@ bool Item_subselect::mark_as_dependent(THD *thd, st_select_lex *select,
/*
+ @brief
+ Update the table bitmaps for the outer references used within a subquery
+*/
+
+bool Item_subselect::update_table_bitmaps_processor(void *arg)
+{
+ List_iterator<Ref_to_outside> it(upper_refs);
+ Ref_to_outside *upper;
+
+ while ((upper= it++))
+ {
+ if (upper->item &&
+ upper->item->walk(&Item::update_table_bitmaps_processor, FALSE, arg))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+/*
Adjust attributes after our parent select has been merged into grandparent
DESCRIPTION
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index a346def72f1..b5894041320 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -256,6 +256,7 @@ public:
@retval FALSE otherwise
*/
bool is_expensive_processor(void *arg) override { return is_expensive(); }
+ bool update_table_bitmaps_processor(void *arg) override;
/**
Get the SELECT_LEX structure associated with this Item.
@@ -277,7 +278,7 @@ public:
Item* build_clone(THD *thd) override { return 0; }
Item* get_copy(THD *thd) override { return 0; }
- bool wrap_tvc_into_select(THD *thd, st_select_lex *tvc_sl);
+ st_select_lex *wrap_tvc_into_select(THD *thd, st_select_lex *tvc_sl);
friend class select_result_interceptor;
friend class Item_in_optimizer;
diff --git a/sql/lock.cc b/sql/lock.cc
index ff215795604..5d502755541 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -746,6 +746,9 @@ static int unlock_external(THD *thd, TABLE **table,uint count)
- GET_LOCK_STORE_LOCKS : Store lock info in TABLE
- GET_LOCK_SKIP_SEQUENCES : Ignore sequences (for temporary unlock)
- GET_LOCK_ON_THD : Store lock in thd->mem_root
+
+ Temporary tables are not locked (as these are single user), except for
+ TRANSACTIONAL_TMP_TABLES as locking is needed to handle transactions.
*/
MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, uint flags)
@@ -762,8 +765,8 @@ MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, uint flags)
{
TABLE *t= table_ptr[i];
- if (t->s->tmp_table != NON_TRANSACTIONAL_TMP_TABLE &&
- t->s->tmp_table != INTERNAL_TMP_TABLE &&
+ if ((likely(!t->s->tmp_table) ||
+ (t->s->tmp_table == TRANSACTIONAL_TMP_TABLE)) &&
(!(flags & GET_LOCK_SKIP_SEQUENCES) || t->s->sequence == 0))
{
lock_count+= t->file->lock_count();
@@ -792,13 +795,13 @@ MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, uint flags)
for (i=0 ; i < count ; i++)
{
- TABLE *table;
+ TABLE *table= table_ptr[i];
enum thr_lock_type lock_type;
THR_LOCK_DATA **locks_start;
- table= table_ptr[i];
- if (table->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE ||
- table->s->tmp_table == INTERNAL_TMP_TABLE ||
- ((flags & GET_LOCK_SKIP_SEQUENCES) && table->s->sequence))
+
+ if (!((likely(!table->s->tmp_table) ||
+ (table->s->tmp_table == TRANSACTIONAL_TMP_TABLE)) &&
+ (!(flags & GET_LOCK_SKIP_SEQUENCES) || table->s->sequence == 0)))
continue;
lock_type= table->reginfo.lock_type;
DBUG_ASSERT(lock_type != TL_WRITE_DEFAULT && lock_type != TL_READ_DEFAULT);
diff --git a/sql/log.cc b/sql/log.cc
index d6b47ff3aa6..3b1322035eb 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -6591,8 +6591,9 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate)
MDL_REQUEST_INIT(&mdl_request, MDL_key::BACKUP, "", "", MDL_BACKUP_COMMIT,
MDL_EXPLICIT);
- thd->mdl_context.acquire_lock(&mdl_request,
- thd->variables.lock_wait_timeout);
+ if (thd->mdl_context.acquire_lock(&mdl_request,
+ thd->variables.lock_wait_timeout))
+ DBUG_RETURN(1);
thd->backup_commit_lock= &mdl_request;
if ((res= thd->wait_for_prior_commit()))
diff --git a/sql/signal_handler.cc b/sql/signal_handler.cc
index 5e3f32eae4e..79bc32cbf19 100644
--- a/sql/signal_handler.cc
+++ b/sql/signal_handler.cc
@@ -15,6 +15,7 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
#include "mariadb.h"
+#include "my_dbug.h"
#include <signal.h>
//#include "sys_vars.h"
@@ -120,8 +121,8 @@ extern "C" sig_handler handle_fatal_signal(int sig)
my_safe_printf_stderr("Fatal " SIGNAL_FMT " while backtracing\n", sig);
goto end;
}
-
segfaulted = 1;
+ DBUG_PRINT("error", ("handling fatal signal"));
curr_time= my_time(0);
localtime_r(&curr_time, &tm);
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 2e1b74bb3ce..4ae27a7e3ce 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -9052,6 +9052,16 @@ static bool print_grants_for_role(THD *thd, ACL_ROLE * role)
}
+static void append_auto_expiration_policy(ACL_USER *acl_user, String *r) {
+ if (!acl_user->password_lifetime)
+ r->append(STRING_WITH_LEN(" PASSWORD EXPIRE NEVER"));
+ else if (acl_user->password_lifetime > 0)
+ {
+ r->append(STRING_WITH_LEN(" PASSWORD EXPIRE INTERVAL "));
+ r->append_longlong(acl_user->password_lifetime);
+ r->append(STRING_WITH_LEN(" DAY"));
+ }
+}
bool mysql_show_create_user(THD *thd, LEX_USER *lex_user)
{
@@ -9111,14 +9121,8 @@ bool mysql_show_create_user(THD *thd, LEX_USER *lex_user)
if (acl_user->password_expired)
result.append(STRING_WITH_LEN(" PASSWORD EXPIRE"));
- else if (!acl_user->password_lifetime)
- result.append(STRING_WITH_LEN(" PASSWORD EXPIRE NEVER"));
- else if (acl_user->password_lifetime > 0)
- {
- result.append(STRING_WITH_LEN(" PASSWORD EXPIRE INTERVAL "));
- result.append_longlong(acl_user->password_lifetime);
- result.append(STRING_WITH_LEN(" DAY"));
- }
+ else
+ append_auto_expiration_policy(acl_user, &result);
protocol->prepare_for_resend();
protocol->store(result.ptr(), result.length(), result.charset());
@@ -9126,6 +9130,28 @@ bool mysql_show_create_user(THD *thd, LEX_USER *lex_user)
{
error= true;
}
+
+ /* MDEV-24114 - PASSWORD EXPIRE and PASSWORD EXPIRE [NEVER | INTERVAL X DAY]
+ are two different mechanisms. To make sure a tool can restore the state
+ of a user account, including both the manual expiration state of the
+ account and the automatic expiration policy attached to it, we should
+ print two statements here, a CREATE USER (printed above) and an ALTER USER */
+ if (acl_user->password_expired && acl_user->password_lifetime > -1) {
+ result.length(0);
+ result.append("ALTER USER ");
+ append_identifier(thd, &result, username, strlen(username));
+ result.append('@');
+ append_identifier(thd, &result, acl_user->host.hostname,
+ acl_user->hostname_length);
+ append_auto_expiration_policy(acl_user, &result);
+ protocol->prepare_for_resend();
+ protocol->store(result.ptr(), result.length(), result.charset());
+ if (protocol->write())
+ {
+ error= true;
+ }
+ }
+
my_eof(thd);
end:
diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc
index 7c1f8596ece..ee7226afd0b 100644
--- a/sql/sql_admin.cc
+++ b/sql/sql_admin.cc
@@ -1454,7 +1454,9 @@ bool Sql_cmd_optimize_table::execute(THD *thd)
/*
Presumably, OPTIMIZE and binlog writing doesn't require synchronization
*/
+ thd->get_stmt_da()->set_overwrite_status(true);
res= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
+ thd->get_stmt_da()->set_overwrite_status(false);
}
m_lex->first_select_lex()->table_list.first= first_table;
m_lex->query_tables= first_table;
@@ -1486,7 +1488,9 @@ bool Sql_cmd_repair_table::execute(THD *thd)
/*
Presumably, REPAIR and binlog writing doesn't require synchronization
*/
+ thd->get_stmt_da()->set_overwrite_status(true);
res= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
+ thd->get_stmt_da()->set_overwrite_status(false);
}
m_lex->first_select_lex()->table_list.first= first_table;
m_lex->query_tables= first_table;
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 10b71781ce4..be288ebaf3b 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -530,7 +530,7 @@ struct LEX_MASTER_INFO
}
host= user= password= log_file_name= ssl_key= ssl_cert= ssl_ca=
- ssl_capath= ssl_cipher= relay_log_name= 0;
+ ssl_capath= ssl_cipher= ssl_crl= ssl_crlpath= relay_log_name= NULL;
pos= relay_log_pos= server_id= port= connect_retry= 0;
heartbeat_period= 0;
ssl= ssl_verify_server_cert= heartbeat_opt=
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index ceb298aefc6..2f88d4f9217 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1172,22 +1172,6 @@ JOIN::prepare(TABLE_LIST *tables_init, COND *conds_init, uint og_num,
FALSE, SELECT_ACL, SELECT_ACL, FALSE))
DBUG_RETURN(-1);
- /*
- Permanently remove redundant parts from the query if
- 1) This is a subquery
- 2) This is the first time this query is optimized (since the
- transformation is permanent
- 3) Not normalizing a view. Removal should take place when a
- query involving a view is optimized, not when the view
- is created
- */
- if (select_lex->master_unit()->item && // 1)
- select_lex->first_cond_optimization && // 2)
- !thd->lex->is_view_context_analysis()) // 3)
- {
- remove_redundant_subquery_clauses(select_lex);
- }
-
/* System Versioning: handle FOR SYSTEM_TIME clause. */
if (select_lex->vers_setup_conds(thd, tables_list) < 0)
DBUG_RETURN(-1);
@@ -1269,6 +1253,23 @@ JOIN::prepare(TABLE_LIST *tables_init, COND *conds_init, uint og_num,
&hidden_group_fields,
&select_lex->select_n_reserved))
DBUG_RETURN(-1);
+
+ /*
+ Permanently remove redundant parts from the query if
+ 1) This is a subquery
+ 2) This is the first time this query is optimized (since the
+ transformation is permanent
+ 3) Not normalizing a view. Removal should take place when a
+ query involving a view is optimized, not when the view
+ is created
+ */
+ if (select_lex->master_unit()->item && // 1)
+ select_lex->first_cond_optimization && // 2)
+ !thd->lex->is_view_context_analysis()) // 3)
+ {
+ remove_redundant_subquery_clauses(select_lex);
+ }
+
/* Resolve the ORDER BY that was skipped, then remove it. */
if (skip_order_by && select_lex !=
select_lex->master_unit()->global_parameters())
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 6fe45fe2de3..b043f83c72c 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -8657,6 +8657,16 @@ bool get_schema_tables_result(JOIN *join,
if (table_list->schema_table->fill_table == 0)
continue;
+ /*
+ Do not fill in tables thare are marked as JT_CONST as these will never
+ be read and they also don't have a tab->read_record.table set!
+ This can happen with queries like
+ SELECT * FROM t1 LEFT JOIN (t1 AS t1b JOIN INFORMATION_SCHEMA.ROUTINES)
+ ON (t1b.a IS NULL);
+ */
+ if (tab->type == JT_CONST)
+ continue;
+
/* skip I_S optimizations specific to get_all_tables */
if (lex->describe &&
(table_list->schema_table->fill_table != get_all_tables))
diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc
index 72a55bfa86b..821448740e7 100644
--- a/sql/sql_statistics.cc
+++ b/sql/sql_statistics.cc
@@ -1021,14 +1021,14 @@ public:
void store_stat_fields()
{
- char buff[MAX_FIELD_WIDTH];
- String val(buff, sizeof(buff), &my_charset_bin);
+ StringBuffer<MAX_FIELD_WIDTH> val;
MY_BITMAP *old_map= dbug_tmp_use_all_columns(stat_table, &stat_table->read_set);
for (uint i= COLUMN_STAT_MIN_VALUE; i <= COLUMN_STAT_HISTOGRAM; i++)
{
Field *stat_field= stat_table->field[i];
- if (table_field->collected_stats->is_null(i))
+ Column_statistics *stats= table_field->collected_stats;
+ if (stats->is_null(i))
stat_field->set_null();
else
{
@@ -1041,47 +1041,37 @@ public:
and move this implementation there
*/
if (table_field->type() == MYSQL_TYPE_BIT)
- stat_field->store(table_field->collected_stats->min_value->val_int(),true);
+ stat_field->store(stats->min_value->val_int(),true);
else
- {
- Field *field= table_field->collected_stats->min_value;
- field->store_to_statistical_minmax_field(stat_field, &val);
- }
+ stats->min_value->store_to_statistical_minmax_field(stat_field, &val);
break;
}
case COLUMN_STAT_MAX_VALUE:
{
if (table_field->type() == MYSQL_TYPE_BIT)
- stat_field->store(table_field->collected_stats->max_value->val_int(),true);
+ stat_field->store(stats->max_value->val_int(),true);
else
- {
- Field *field= table_field->collected_stats->max_value;
- field->store_to_statistical_minmax_field(stat_field, &val);
- }
+ stats->max_value->store_to_statistical_minmax_field(stat_field, &val);
break;
}
case COLUMN_STAT_NULLS_RATIO:
- stat_field->store(table_field->collected_stats->get_nulls_ratio());
+ stat_field->store(stats->get_nulls_ratio());
break;
case COLUMN_STAT_AVG_LENGTH:
- stat_field->store(table_field->collected_stats->get_avg_length());
+ stat_field->store(stats->get_avg_length());
break;
case COLUMN_STAT_AVG_FREQUENCY:
- stat_field->store(table_field->collected_stats->get_avg_frequency());
+ stat_field->store(stats->get_avg_frequency());
break;
case COLUMN_STAT_HIST_SIZE:
- stat_field->store(table_field->collected_stats->histogram.get_size());
+ stat_field->store(stats->histogram.get_size());
break;
case COLUMN_STAT_HIST_TYPE:
- stat_field->store(table_field->collected_stats->histogram.get_type() +
- 1);
+ stat_field->store(stats->histogram.get_type() + 1);
break;
case COLUMN_STAT_HISTOGRAM:
- const char * col_histogram=
- (const char *) (table_field->collected_stats->histogram.get_values());
- stat_field->store(col_histogram,
- table_field->collected_stats->histogram.get_size(),
- &my_charset_bin);
+ stat_field->store((char *)stats->histogram.get_values(),
+ stats->histogram.get_size(), &my_charset_bin);
break;
}
}
@@ -1139,14 +1129,20 @@ public:
{
Field *field= table_field->read_stats->min_value;
field->set_notnull();
- field->store_from_statistical_minmax_field(stat_field, &val);
+ if (table_field->type() == MYSQL_TYPE_BIT)
+ field->store(stat_field->val_int(), true);
+ else
+ field->store_from_statistical_minmax_field(stat_field, &val);
break;
}
case COLUMN_STAT_MAX_VALUE:
{
Field *field= table_field->read_stats->max_value;
field->set_notnull();
- field->store_from_statistical_minmax_field(stat_field, &val);
+ if (table_field->type() == MYSQL_TYPE_BIT)
+ field->store(stat_field->val_int(), true);
+ else
+ field->store_from_statistical_minmax_field(stat_field, &val);
break;
}
case COLUMN_STAT_NULLS_RATIO:
@@ -2101,20 +2097,24 @@ void create_min_max_statistical_fields_for_table_share(THD *thd,
int alloc_statistics_for_table(THD* thd, TABLE *table)
{
Field **field_ptr;
- uint fields;
DBUG_ENTER("alloc_statistics_for_table");
+ uint columns= 0;
+ for (field_ptr= table->field; *field_ptr; field_ptr++)
+ {
+ if (bitmap_is_set(table->read_set, (*field_ptr)->field_index))
+ columns++;
+ }
Table_statistics *table_stats=
(Table_statistics *) alloc_root(&table->mem_root,
sizeof(Table_statistics));
- fields= table->s->fields ;
Column_statistics_collected *column_stats=
(Column_statistics_collected *) alloc_root(&table->mem_root,
sizeof(Column_statistics_collected) *
- (fields+1));
+ columns);
uint keys= table->s->keys;
Index_statistics *index_stats=
@@ -2125,16 +2125,6 @@ int alloc_statistics_for_table(THD* thd, TABLE *table)
ulonglong *idx_avg_frequency= (ulonglong*) alloc_root(&table->mem_root,
sizeof(ulonglong) * key_parts);
- if (table->file->ha_rnd_init(TRUE))
- DBUG_RETURN(1);
- table->file->ha_rnd_end();
-
- uint columns= 0;
- for (field_ptr= table->field; *field_ptr; field_ptr++)
- {
- if (bitmap_is_set(table->read_set, (*field_ptr)->field_index))
- columns++;
- }
uint hist_size= thd->variables.histogram_size;
Histogram_type hist_type= (Histogram_type) (thd->variables.histogram_type);
uchar *histogram= NULL;
@@ -2156,19 +2146,17 @@ int alloc_statistics_for_table(THD* thd, TABLE *table)
table_stats->idx_avg_frequency= idx_avg_frequency;
table_stats->histograms= histogram;
- memset(column_stats, 0, sizeof(Column_statistics) * (fields+1));
+ memset(column_stats, 0, sizeof(Column_statistics) * columns);
- for (field_ptr= table->field; *field_ptr; field_ptr++, column_stats++)
+ for (field_ptr= table->field; *field_ptr; field_ptr++)
{
- (*field_ptr)->collected_stats= column_stats;
- (*field_ptr)->collected_stats->max_value= NULL;
- (*field_ptr)->collected_stats->min_value= NULL;
if (bitmap_is_set(table->read_set, (*field_ptr)->field_index))
{
column_stats->histogram.set_size(hist_size);
column_stats->histogram.set_type(hist_type);
column_stats->histogram.set_values(histogram);
histogram+= hist_size;
+ (*field_ptr)->collected_stats= column_stats++;
}
}
@@ -2663,7 +2651,7 @@ int collect_statistics_for_table(THD *thd, TABLE *table)
for (field_ptr= table->field; *field_ptr; field_ptr++)
{
table_field= *field_ptr;
- if (!bitmap_is_set(table->read_set, table_field->field_index))
+ if (!table_field->collected_stats)
continue;
table_field->collected_stats->init(thd, table_field);
}
@@ -2688,7 +2676,7 @@ int collect_statistics_for_table(THD *thd, TABLE *table)
for (field_ptr= table->field; *field_ptr; field_ptr++)
{
table_field= *field_ptr;
- if (!bitmap_is_set(table->read_set, table_field->field_index))
+ if (!table_field->collected_stats)
continue;
if ((rc= table_field->collected_stats->add()))
break;
@@ -2718,7 +2706,7 @@ int collect_statistics_for_table(THD *thd, TABLE *table)
for (field_ptr= table->field; *field_ptr; field_ptr++)
{
table_field= *field_ptr;
- if (!bitmap_is_set(table->read_set, table_field->field_index))
+ if (!table_field->collected_stats)
continue;
bitmap_set_bit(table->write_set, table_field->field_index);
if (!rc)
@@ -2822,7 +2810,7 @@ int update_statistics_for_table(THD *thd, TABLE *table)
for (Field **field_ptr= table->field; *field_ptr; field_ptr++)
{
Field *table_field= *field_ptr;
- if (!bitmap_is_set(table->read_set, table_field->field_index))
+ if (!table_field->collected_stats)
continue;
restore_record(stat_table, s->default_values);
column_stat.set_key_fields(table_field);
@@ -3757,6 +3745,7 @@ double get_column_range_cardinality(Field *field,
if (!table->stats_is_read)
return tab_records;
+ THD *thd= table->in_use;
double col_nulls= tab_records * col_stats->get_nulls_ratio();
double col_non_nulls= tab_records - col_nulls;
@@ -3787,7 +3776,7 @@ double get_column_range_cardinality(Field *field,
col_stats->min_max_values_are_provided())
{
Histogram *hist= &col_stats->histogram;
- if (hist->is_available())
+ if (hist->is_usable(thd))
{
store_key_image_to_rec(field, (uchar *) min_endp->key,
field->key_length());
@@ -3831,10 +3820,10 @@ double get_column_range_cardinality(Field *field,
max_mp_pos= 1.0;
Histogram *hist= &col_stats->histogram;
- if (!hist->is_available())
- sel= (max_mp_pos - min_mp_pos);
- else
+ if (hist->is_usable(thd))
sel= hist->range_selectivity(min_mp_pos, max_mp_pos);
+ else
+ sel= (max_mp_pos - min_mp_pos);
res= col_non_nulls * sel;
set_if_bigger(res, col_stats->get_avg_frequency());
}
diff --git a/sql/sql_statistics.h b/sql/sql_statistics.h
index 20ecf06bfee..35b3aa33acc 100644
--- a/sql/sql_statistics.h
+++ b/sql/sql_statistics.h
@@ -239,6 +239,17 @@ public:
bool is_available() { return get_size() > 0 && get_values(); }
+ /*
+ This function checks that histograms should be usable only when
+ 1) the level of optimizer_use_condition_selectivity > 3
+ 2) histograms have been collected
+ */
+ bool is_usable(THD *thd)
+ {
+ return thd->variables.optimizer_use_condition_selectivity > 3 &&
+ is_available();
+ }
+
void set_value(uint i, double val)
{
switch (type) {
diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc
index 5e89c4d19ee..2bf99993a50 100644
--- a/sql/sql_truncate.cc
+++ b/sql/sql_truncate.cc
@@ -427,20 +427,23 @@ bool Sql_cmd_truncate_table::truncate_table(THD *thd, TABLE_LIST *table_ref)
bool hton_can_recreate;
#ifdef WITH_WSREP
- if (WSREP(thd))
+ if (WSREP(thd) && wsrep_thd_is_local(thd))
{
wsrep::key_array keys;
- wsrep_append_fk_parent_table(thd, table_ref, &keys);
- if (keys.empty())
+ /* Do not start TOI if table is not found */
+ if (!wsrep_append_fk_parent_table(thd, table_ref, &keys))
{
- WSREP_TO_ISOLATION_BEGIN_IF(table_ref->db.str, table_ref->table_name.str, NULL)
+ if (keys.empty())
{
- DBUG_RETURN(TRUE);
- }
- } else {
- WSREP_TO_ISOLATION_BEGIN_FK_TABLES(NULL, NULL, table_ref, &keys)
- {
- DBUG_RETURN(TRUE);
+ WSREP_TO_ISOLATION_BEGIN_IF(table_ref->db.str, table_ref->table_name.str, NULL)
+ {
+ DBUG_RETURN(TRUE);
+ }
+ } else {
+ WSREP_TO_ISOLATION_BEGIN_FK_TABLES(NULL, NULL, table_ref, &keys)
+ {
+ DBUG_RETURN(TRUE);
+ }
}
}
}
diff --git a/sql/sql_tvc.cc b/sql/sql_tvc.cc
index 9a7084cdca2..e8a201aecfc 100644
--- a/sql/sql_tvc.cc
+++ b/sql/sql_tvc.cc
@@ -372,6 +372,13 @@ int table_value_constr::save_explain_data_intern(THD *thd,
if (select_lex->master_unit()->derived)
explain->connection_type= Explain_node::EXPLAIN_NODE_DERIVED;
+ for (SELECT_LEX_UNIT *unit= select_lex->first_inner_unit();
+ unit;
+ unit= unit->next_unit())
+ {
+ explain->add_child(unit->first_select()->select_number);
+ }
+
output->add_node(explain);
if (select_lex->is_top_level_node())
@@ -396,9 +403,14 @@ bool table_value_constr::optimize(THD *thd)
thd->lex->explain && // for "SET" command in SPs.
(!thd->lex->explain->get_select(select_lex->select_number)))
{
- return save_explain_data_intern(thd, thd->lex->explain);
+ if (save_explain_data_intern(thd, thd->lex->explain))
+ return true;
}
- return 0;
+
+ if (select_lex->optimize_unflattened_subqueries(true))
+ return true;
+
+ return false;
}
@@ -811,11 +823,12 @@ st_select_lex *wrap_tvc_with_tail(THD *thd, st_select_lex *tvc_sl)
SELECT * FROM (VALUES (v1), ... (vn)) tvc_x
and replaces the subselect with the result of the transformation.
- @retval false if successfull
- true otherwise
+ @retval wrapping select if successful
+ 0 otherwise
*/
-bool Item_subselect::wrap_tvc_into_select(THD *thd, st_select_lex *tvc_sl)
+st_select_lex *
+Item_subselect::wrap_tvc_into_select(THD *thd, st_select_lex *tvc_sl)
{
LEX *lex= thd->lex;
/* SELECT_LEX object where the transformation is performed */
@@ -826,12 +839,12 @@ bool Item_subselect::wrap_tvc_into_select(THD *thd, st_select_lex *tvc_sl)
if (engine->engine_type() == subselect_engine::SINGLE_SELECT_ENGINE)
((subselect_single_select_engine *) engine)->change_select(wrapper_sl);
lex->current_select= wrapper_sl;
- return false;
+ return wrapper_sl;
}
else
{
lex->current_select= parent_select;
- return true;
+ return 0;
}
}
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 76a7dc47745..35ceeeff43a 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -3050,14 +3050,18 @@ bool multi_update::send_eof()
DBUG_ASSERT(trans_safe || !updated ||
thd->transaction->stmt.modified_non_trans_table);
- if (likely(local_error != 0))
- error_handled= TRUE; // to force early leave from ::abort_result_set()
-
- if (unlikely(local_error > 0)) // if the above log write did not fail ...
+ if (unlikely(local_error))
{
- /* Safety: If we haven't got an error before (can happen in do_updates) */
- my_message(ER_UNKNOWN_ERROR, "An error occurred in multi-table update",
- MYF(0));
+ error_handled= TRUE; // to force early leave from ::abort_result_set()
+ if (thd->killed == NOT_KILLED && !thd->get_stmt_da()->is_set())
+ {
+ /*
+ No error message was sent and query was not killed (in which case
+ mysql_execute_command() will send the error mesage).
+ */
+ my_message(ER_UNKNOWN_ERROR, "An error occurred in multi-table update",
+ MYF(0));
+ }
DBUG_RETURN(TRUE);
}
diff --git a/sql/structs.h b/sql/structs.h
index 76129f2abf7..bcd38ffbdd6 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -92,7 +92,7 @@ class engine_option_value;
struct ha_index_option_struct;
typedef struct st_key {
- uint key_length; /* Tot length of key */
+ uint key_length; /* total length of user defined key parts */
ulong flags; /* dupp key and pack flags */
uint user_defined_key_parts; /* How many key_parts */
uint usable_key_parts; /* Should normally be = user_defined_key_parts */
diff --git a/sql/table.cc b/sql/table.cc
index 4f65dbd65f4..f4bdbdeac5a 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -2943,7 +2943,8 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
key_part->key_part_flag|= field->key_part_flag();
uint16 key_part_length_bytes= field->key_part_length_bytes();
key_part->store_length+= key_part_length_bytes;
- keyinfo->key_length+= key_part_length_bytes;
+ if (i < keyinfo->user_defined_key_parts)
+ keyinfo->key_length+= key_part_length_bytes;
if (i == 0 && key != primary_key)
field->flags |= (((keyinfo->flags & HA_NOSAME ||
@@ -3037,7 +3038,6 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
set_if_bigger(share->max_key_length,keyinfo->key_length+
keyinfo->user_defined_key_parts);
- share->total_key_length+= keyinfo->key_length;
/*
MERGE tables do not have unique indexes. But every key could be
an unique index on the underlying MyISAM table. (Bug #10400)
diff --git a/sql/table.h b/sql/table.h
index 53f385be7fd..9eefd915844 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -815,7 +815,7 @@ struct TABLE_SHARE
uint rec_buff_length; /* Size of table->record[] buffer */
uint keys, key_parts;
uint ext_key_parts; /* Total number of key parts in extended keys */
- uint max_key_length, max_unique_length, total_key_length;
+ uint max_key_length, max_unique_length;
uint uniques; /* Number of UNIQUE index */
uint db_create_options; /* Create options from database */
uint db_options_in_use; /* Options in use */
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc
index aa6a7a2ca63..f14bf06800a 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -1261,10 +1261,17 @@ void wsrep_keys_free(wsrep_key_arr_t* key_arr)
key_arr->keys_len= 0;
}
-void
+/*!
+ * @param thd thread
+ * @param tables list of tables
+ * @param keys prepared keys
+
+ * @return true if parent table append was successfull, otherwise false.
+*/
+bool
wsrep_append_fk_parent_table(THD* thd, TABLE_LIST* tables, wsrep::key_array* keys)
{
- if (!WSREP(thd) || !WSREP_CLIENT(thd)) return;
+ bool fail= false;
TABLE_LIST *table;
thd->release_transactional_locks();
@@ -1275,6 +1282,8 @@ wsrep_append_fk_parent_table(THD* thd, TABLE_LIST* tables, wsrep::key_array* key
open_tables(thd, &tables, &counter, MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL))
{
WSREP_DEBUG("unable to open table for FK checks for %s", thd->query());
+ fail= true;
+ goto exit;
}
for (table= tables; table; table= table->next_local)
@@ -1296,14 +1305,18 @@ wsrep_append_fk_parent_table(THD* thd, TABLE_LIST* tables, wsrep::key_array* key
}
}
+exit:
/* close the table and release MDL locks */
close_thread_tables(thd);
thd->mdl_context.rollback_to_savepoint(mdl_savepoint);
for (table= tables; table; table= table->next_local)
{
table->table= NULL;
+ table->next_global= NULL;
table->mdl_request.ticket= NULL;
}
+
+ return fail;
}
/*!
diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h
index 73ee5d7b4c1..28c012a607c 100644
--- a/sql/wsrep_mysqld.h
+++ b/sql/wsrep_mysqld.h
@@ -216,7 +216,7 @@ wsrep_sync_wait_upto (THD* thd, wsrep_gtid_t* upto, int timeout);
extern void wsrep_last_committed_id (wsrep_gtid_t* gtid);
extern int wsrep_check_opts();
extern void wsrep_prepend_PATH (const char* path);
-void wsrep_append_fk_parent_table(THD* thd, TABLE_LIST* table, wsrep::key_array* keys);
+extern bool wsrep_append_fk_parent_table(THD* thd, TABLE_LIST* table, wsrep::key_array* keys);
/* Other global variables */
extern wsrep_seqno_t wsrep_locked_seqno;
diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc
index dc51c06bcc3..f6ed684b3ea 100644
--- a/sql/wsrep_sst.cc
+++ b/sql/wsrep_sst.cc
@@ -772,8 +772,20 @@ static size_t estimate_cmd_len (bool* extra_args)
char c;
while ((c = *arg++) != 0)
{
- /* A whitespace or a single quote requires double quotation marks: */
- if (isspace(c) || c == '\'')
+ /*
+ Space, single quote, ampersand, and I/O redirection characters
+ require text to be enclosed in double quotes:
+ */
+ if (isspace(c) || c == '\'' || c == '&' || c == '|' ||
+#ifdef __WIN__
+ c == '>' || c == '<')
+#else
+ /*
+ The semicolon is used to separate shell commands, so it must be
+ enclosed in double quotes as well:
+ */
+ c == '>' || c == '<' || c == ';')
+#endif
{
quotation= true;
}
@@ -796,10 +808,19 @@ static size_t estimate_cmd_len (bool* extra_args)
while ((c = *arg++) != 0)
{
/*
- A whitespace or a single quote requires double
- quotation marks:
+ Space, single quote, ampersand, and I/O redirection characters
+ require text to be enclosed in double quotes:
+ */
+ if (isspace(c) || c == '\'' || c == '&' || c == '|' ||
+#ifdef __WIN__
+ c == '>' || c == '<')
+#else
+ /*
+ The semicolon is used to separate shell commands, so it must be
+ enclosed in double quotes as well:
*/
- if (isspace(c) || c == '\'')
+ c == '>' || c == '<' || c == ';')
+#endif
{
quotation= true;
}
@@ -880,8 +901,20 @@ static void copy_orig_argv (char* cmd_str)
char c;
while ((c = *arg_scan++) != 0)
{
- /* A whitespace or a single quote requires double quotation marks: */
- if (isspace(c) || c == '\'')
+ /*
+ Space, single quote, ampersand, and I/O redirection characters
+ require text to be enclosed in double quotes:
+ */
+ if (isspace(c) || c == '\'' || c == '&' || c == '|' ||
+#ifdef __WIN__
+ c == '>' || c == '<')
+#else
+ /*
+ The semicolon is used to separate shell commands, so it must be
+ enclosed in double quotes as well:
+ */
+ c == '>' || c == '<' || c == ';')
+#endif
{
quotation= true;
}
@@ -955,10 +988,19 @@ static void copy_orig_argv (char* cmd_str)
while ((c = *arg_scan++) != 0)
{
/*
- A whitespace or a single quote requires double
- quotation marks:
+ Space, single quote, ampersand, and I/O redirection characters
+ require text to be enclosed in double quotes:
+ */
+ if (isspace(c) || c == '\'' || c == '&' || c == '|' ||
+#ifdef __WIN__
+ c == '>' || c == '<')
+#else
+ /*
+ The semicolon is used to separate shell commands, so it must be
+ enclosed in double quotes as well:
*/
- if (isspace(c) || c == '\'')
+ c == '>' || c == '<' || c == ';')
+#endif
{
quotation= true;
}
diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc
index 3a3f3b8c3b7..9ba8f081c83 100644
--- a/sql/wsrep_var.cc
+++ b/sql/wsrep_var.cc
@@ -497,15 +497,21 @@ bool wsrep_provider_options_check(sys_var *self, THD* thd, set_var* var)
bool wsrep_provider_options_update(sys_var *self, THD* thd, enum_var_type type)
{
- enum wsrep::provider::status ret=
- Wsrep_server_state::instance().provider().options(wsrep_provider_options);
- if (ret)
+ if (wsrep_provider_options)
{
- WSREP_ERROR("Set options returned %d", ret);
- refresh_provider_options();
- return true;
+ enum wsrep::provider::status ret=
+ Wsrep_server_state::instance().provider().options(wsrep_provider_options);
+ if (ret)
+ {
+ WSREP_ERROR("Set options returned %d", ret);
+ goto err;
+ }
+
+ return refresh_provider_options();
}
- return refresh_provider_options();
+err:
+ refresh_provider_options();
+ return true;
}
void wsrep_provider_options_init(const char* value)