summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/ha_partition.cc17
-rw-r--r--sql/item_strfunc.cc2
-rw-r--r--sql/opt_range.cc38
-rw-r--r--sql/share/errmsg-utf8.txt2
-rw-r--r--sql/sql_base.cc10
-rw-r--r--sql/sql_class.cc48
-rw-r--r--sql/sql_class.h40
-rw-r--r--sql/sql_insert.cc1
-rw-r--r--sql/sql_select.cc305
-rw-r--r--sql/sql_table.cc30
-rw-r--r--sql/sql_yacc.yy6
-rw-r--r--sql/sql_yacc_ora.yy6
-rw-r--r--sql/wsrep_mysqld.cc15
-rw-r--r--sql/wsrep_mysqld.h9
-rw-r--r--sql/wsrep_sst.cc8
-rw-r--r--sql/wsrep_thd.cc21
16 files changed, 342 insertions, 216 deletions
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 75f6585f847..090b26a036b 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -4095,8 +4095,21 @@ int ha_partition::start_stmt(THD *thd, thr_lock_type lock_type)
/* Add partition to be called in reset(). */
bitmap_set_bit(&m_partitions_to_reset, i);
}
- if (lock_type == F_WRLCK && m_part_info->part_expr)
- m_part_info->part_expr->walk(&Item::register_field_in_read_map, 1, 0);
+ switch (lock_type)
+ {
+ case TL_WRITE_ALLOW_WRITE:
+ case TL_WRITE_CONCURRENT_INSERT:
+ case TL_WRITE_DELAYED:
+ case TL_WRITE_DEFAULT:
+ case TL_WRITE_LOW_PRIORITY:
+ case TL_WRITE:
+ case TL_WRITE_ONLY:
+ if (m_part_info->part_expr)
+ m_part_info->part_expr->walk(&Item::register_field_in_read_map, 1, 0);
+ if (m_part_info->part_type == VERSIONING_PARTITION)
+ m_part_info->vers_set_hist_part(thd);
+ default:;
+ }
DBUG_RETURN(error);
}
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 7151e8966ee..98da93ae699 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -3176,7 +3176,7 @@ bool Item_func_pad::fix_length_and_dec()
DBUG_ASSERT(collation.collation->mbmaxlen > 0);
if (args[1]->const_item() && !args[1]->is_expensive())
{
- fix_char_length(Repeat_count(args[1]).count());
+ fix_char_length_ulonglong(Repeat_count(args[1]).count());
return false;
}
max_length= MAX_BLOB_WIDTH;
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index d0c4ed2ffbc..536dc0383a9 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -2692,6 +2692,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
KEY_PART *key_parts;
KEY *key_info;
PARAM param;
+ bool force_group_by = false;
if (check_stack_overrun(thd, 2*STACK_MIN_SIZE + sizeof(PARAM), buff))
DBUG_RETURN(0); // Fatal error flag is set
@@ -2856,6 +2857,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
Try to construct a QUICK_GROUP_MIN_MAX_SELECT.
Notice that it can be constructed no matter if there is a range tree.
*/
+ DBUG_EXECUTE_IF("force_group_by", force_group_by = true; );
if (!only_single_index_range_scan)
group_trp= get_best_group_min_max(&param, tree, best_read_time);
if (group_trp)
@@ -2867,11 +2869,15 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
if (unlikely(thd->trace_started()))
group_trp->trace_basic_info(&param, &grp_summary);
- if (group_trp->read_cost < best_read_time)
+ if (group_trp->read_cost < best_read_time || force_group_by)
{
grp_summary.add("chosen", true);
best_trp= group_trp;
best_read_time= best_trp->read_cost;
+ if (force_group_by)
+ {
+ goto force_plan;
+ }
}
else
grp_summary.add("chosen", false).add("cause", "cost");
@@ -2977,6 +2983,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
}
}
+force_plan:
thd->mem_root= param.old_root;
/* If we got a read plan, create a quick select from it. */
@@ -12189,13 +12196,28 @@ int QUICK_RANGE_SELECT::get_next_prefix(uint prefix_length,
DBUG_ASSERT(cur_prefix != NULL);
result= file->ha_index_read_map(record, cur_prefix, keypart_map,
HA_READ_AFTER_KEY);
- if (result || last_range->max_keypart_map == 0)
- DBUG_RETURN(result);
-
- key_range previous_endpoint;
- last_range->make_max_endpoint(&previous_endpoint, prefix_length, keypart_map);
- if (file->compare_key(&previous_endpoint) <= 0)
- DBUG_RETURN(0);
+ if (result || last_range->max_keypart_map == 0) {
+ /*
+ Only return if actual failure occurred. For HA_ERR_KEY_NOT_FOUND
+ or HA_ERR_END_OF_FILE, we just want to continue to reach the next
+ set of ranges. It is possible for the storage engine to return
+ HA_ERR_KEY_NOT_FOUND/HA_ERR_END_OF_FILE even when there are more
+ keys if it respects the end range set by the read_range_first call
+ below.
+ */
+ if (result != HA_ERR_KEY_NOT_FOUND && result != HA_ERR_END_OF_FILE)
+ DBUG_RETURN(result);
+ } else {
+ /*
+ For storage engines that don't respect end range, check if we've
+ moved past the current range.
+ */
+ key_range previous_endpoint;
+ last_range->make_max_endpoint(&previous_endpoint, prefix_length,
+ keypart_map);
+ if (file->compare_key(&previous_endpoint) <= 0)
+ DBUG_RETURN(0);
+ }
}
uint count= ranges.elements - (uint)(cur_range - (QUICK_RANGE**) ranges.buffer);
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index c64f60f3562..13d2b0b0cff 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -7931,3 +7931,5 @@ ER_PERIOD_CONSTRAINT_DROP
eng "Can't DROP CONSTRAINT `%s`. Use DROP PERIOD `%s` for this"
ER_TOO_LONG_KEYPART 42000 S1009
eng "Specified key part was too long; max key part length is %u bytes"
+ER_VERS_NO_PERIOD
+ eng "No 'PERIOD FOR SYSTEM_TIME' in system-versioned %`s" \ No newline at end of file
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 881f2662345..4cf9b152940 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -2608,6 +2608,7 @@ unlink_all_closed_tables(THD *thd, MYSQL_LOCK *lock, size_t reopen_count)
DBUG_ASSERT(thd->open_tables == m_reopen_array[reopen_count]);
thd->open_tables->pos_in_locked_tables->table= NULL;
+ thd->open_tables->pos_in_locked_tables= NULL;
close_thread_table(thd, &thd->open_tables);
}
@@ -8463,8 +8464,8 @@ fill_record(THD *thd, TABLE *table_arg, List<Item> &fields, List<Item> &values,
rfield->field_index == table->next_number_field->field_index)
table->auto_increment_field_not_null= TRUE;
Item::Type type= value->type();
- bool vers_sys_field= table->versioned() && rfield->vers_sys_field();
- if ((rfield->vcol_info || vers_sys_field) &&
+ const bool skip_sys_field= rfield->vers_sys_field(); // TODO: && !thd->vers_modify_history() [MDEV-16546]
+ if ((rfield->vcol_info || skip_sys_field) &&
type != Item::DEFAULT_VALUE_ITEM &&
type != Item::NULL_ITEM &&
table->s->table_category != TABLE_CATEGORY_TEMPORARY)
@@ -8473,15 +8474,14 @@ fill_record(THD *thd, TABLE *table_arg, List<Item> &fields, List<Item> &values,
ER_WARNING_NON_DEFAULT_VALUE_FOR_GENERATED_COLUMN,
ER_THD(thd, ER_WARNING_NON_DEFAULT_VALUE_FOR_GENERATED_COLUMN),
rfield->field_name.str, table->s->table_name.str);
- if (vers_sys_field)
- continue;
}
if (only_unvers_fields && !rfield->vers_update_unversioned())
only_unvers_fields= false;
if (rfield->stored_in_db())
{
- if (unlikely(value->save_in_field(rfield, 0) < 0) && !ignore_errors)
+ if (!skip_sys_field &&
+ unlikely(value->save_in_field(rfield, 0) < 0) && !ignore_errors)
{
my_message(ER_UNKNOWN_ERROR, ER_THD(thd, ER_UNKNOWN_ERROR), MYF(0));
goto err;
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 64cfcb89ac6..363c5d35499 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -4881,12 +4881,6 @@ extern "C" int thd_slave_thread(const MYSQL_THD thd)
}
-extern "C" int thd_rpl_stmt_based(const MYSQL_THD thd)
-{
- return thd &&
- !thd->is_current_stmt_binlog_format_row() &&
- !thd->is_current_stmt_binlog_disabled();
-}
/* Returns high resolution timestamp for the start
@@ -6226,6 +6220,48 @@ int THD::decide_logging_format(TABLE_LIST *tables)
DBUG_RETURN(0);
}
+int THD::decide_logging_format_low(TABLE *table)
+{
+ /*
+ INSERT...ON DUPLICATE KEY UPDATE on a table with more than one unique keys
+ can be unsafe.
+ */
+ if(wsrep_binlog_format() <= BINLOG_FORMAT_STMT &&
+ !is_current_stmt_binlog_format_row() &&
+ !lex->is_stmt_unsafe() &&
+ lex->sql_command == SQLCOM_INSERT &&
+ lex->duplicates == DUP_UPDATE)
+ {
+ uint unique_keys= 0;
+ uint keys= table->s->keys, i= 0;
+ Field *field;
+ for (KEY* keyinfo= table->s->key_info;
+ i < keys && unique_keys <= 1; i++, keyinfo++)
+ if (keyinfo->flags & HA_NOSAME &&
+ !(keyinfo->key_part->field->flags & AUTO_INCREMENT_FLAG &&
+ //User given auto inc can be unsafe
+ !keyinfo->key_part->field->val_int()))
+ {
+ for (uint j= 0; j < keyinfo->user_defined_key_parts; j++)
+ {
+ field= keyinfo->key_part[j].field;
+ if(!bitmap_is_set(table->write_set,field->field_index))
+ goto exit;
+ }
+ unique_keys++;
+exit:;
+ }
+
+ if (unique_keys > 1)
+ {
+ lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_INSERT_TWO_KEYS);
+ binlog_unsafe_warning_flags|= lex->get_stmt_unsafe_flags();
+ set_current_stmt_binlog_format_row_if_mixed();
+ return 1;
+ }
+ }
+ return 0;
+}
/*
Implementation of interface to write rows to the binary log through the
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 5fac4369623..2b46fc69365 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -2437,6 +2437,20 @@ public:
/* container for handler's private per-connection data */
Ha_data ha_data[MAX_HA];
+ /**
+ Bit field for the state of binlog warnings.
+
+ The first Lex::BINLOG_STMT_UNSAFE_COUNT bits list all types of
+ unsafeness that the current statement has.
+
+ This must be a member of THD and not of LEX, because warnings are
+ detected and issued in different places (@c
+ decide_logging_format() and @c binlog_query(), respectively).
+ Between these calls, the THD->lex object may change; e.g., if a
+ stored routine is invoked. Only THD persists between the calls.
+ */
+ uint32 binlog_unsafe_warning_flags;
+
#ifndef MYSQL_CLIENT
binlog_cache_mngr * binlog_setup_trx_data();
@@ -2546,20 +2560,6 @@ private:
*/
enum_binlog_format current_stmt_binlog_format;
- /**
- Bit field for the state of binlog warnings.
-
- The first Lex::BINLOG_STMT_UNSAFE_COUNT bits list all types of
- unsafeness that the current statement has.
-
- This must be a member of THD and not of LEX, because warnings are
- detected and issued in different places (@c
- decide_logging_format() and @c binlog_query(), respectively).
- Between these calls, the THD->lex object may change; e.g., if a
- stored routine is invoked. Only THD persists between the calls.
- */
- uint32 binlog_unsafe_warning_flags;
-
/*
Number of outstanding table maps, i.e., table maps in the
transaction cache.
@@ -4536,6 +4536,18 @@ public:
}
void leave_locked_tables_mode();
int decide_logging_format(TABLE_LIST *tables);
+ /*
+ In Some cases when decide_logging_format is called it does not have all
+ information to decide the logging format. So that cases we call decide_logging_format_2
+ at later stages in execution.
+ One example would be binlog format for IODKU but column with unique key is not inserted.
+ We dont have inserted columns info when we call decide_logging_format so on later stage we call
+ decide_logging_format_low
+
+ @returns 0 if no format is changed
+ 1 if there is change in binlog format
+ */
+ int decide_logging_format_low(TABLE *table);
enum need_invoker { INVOKER_NONE=0, INVOKER_USER, INVOKER_ROLE};
void binlog_invoker(bool role) { m_binlog_invoker= role ? INVOKER_ROLE : INVOKER_USER; }
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 8db6aac6846..7825a7742ef 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1061,6 +1061,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
break;
}
+ thd->decide_logging_format_low(table);
#ifndef EMBEDDED_LIBRARY
if (lock_type == TL_WRITE_DELAYED)
{
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 6e2b10b907e..b1336681ac4 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -760,173 +760,39 @@ void vers_select_conds_t::print(String *str, enum_query_type query_type) const
}
}
-static
-Item* period_get_condition(THD *thd, TABLE_LIST *table, SELECT_LEX *select,
- vers_select_conds_t *conds, bool timestamp)
-{
- DBUG_ASSERT(table);
- DBUG_ASSERT(table->table);
-#define newx new (thd->mem_root)
- TABLE_SHARE *share= table->table->s;
- const TABLE_SHARE::period_info_t *period= conds->period;
-
- const LEX_CSTRING &fstart= period->start_field(share)->field_name;
- const LEX_CSTRING &fend= period->end_field(share)->field_name;
-
- conds->field_start= newx Item_field(thd, &select->context,
- table->db.str, table->alias.str,
- thd->make_clex_string(fstart));
- conds->field_end= newx Item_field(thd, &select->context,
- table->db.str, table->alias.str,
- thd->make_clex_string(fend));
-
- Item *cond1= NULL, *cond2= NULL, *cond3= NULL, *curr= NULL;
- if (timestamp)
- {
- MYSQL_TIME max_time;
- switch (conds->type)
- {
- case SYSTEM_TIME_UNSPECIFIED:
- thd->variables.time_zone->gmt_sec_to_TIME(&max_time, TIMESTAMP_MAX_VALUE);
- max_time.second_part= TIME_MAX_SECOND_PART;
- curr= newx Item_datetime_literal(thd, &max_time, TIME_SECOND_PART_DIGITS);
- cond1= newx Item_func_eq(thd, conds->field_end, curr);
- break;
- case SYSTEM_TIME_AS_OF:
- cond1= newx Item_func_le(thd, conds->field_start, conds->start.item);
- cond2= newx Item_func_gt(thd, conds->field_end, conds->start.item);
- break;
- case SYSTEM_TIME_FROM_TO:
- cond1= newx Item_func_lt(thd, conds->field_start, conds->end.item);
- cond2= newx Item_func_gt(thd, conds->field_end, conds->start.item);
- cond3= newx Item_func_lt(thd, conds->start.item, conds->end.item);
- break;
- case SYSTEM_TIME_BETWEEN:
- cond1= newx Item_func_le(thd, conds->field_start, conds->end.item);
- cond2= newx Item_func_gt(thd, conds->field_end, conds->start.item);
- cond3= newx Item_func_le(thd, conds->start.item, conds->end.item);
- break;
- case SYSTEM_TIME_BEFORE:
- cond1= newx Item_func_lt(thd, conds->field_end, conds->start.item);
- break;
- default:
- DBUG_ASSERT(0);
- }
- }
- else
- {
- DBUG_ASSERT(table->table->s && table->table->s->db_plugin);
-
- Item *trx_id0= conds->start.item;
- Item *trx_id1= conds->end.item;
- if (conds->start.item && conds->start.unit == VERS_TIMESTAMP)
- {
- bool backwards= conds->type != SYSTEM_TIME_AS_OF;
- trx_id0= newx Item_func_trt_id(thd, conds->start.item,
- TR_table::FLD_TRX_ID, backwards);
- }
- if (conds->end.item && conds->end.unit == VERS_TIMESTAMP)
- {
- trx_id1= newx Item_func_trt_id(thd, conds->end.item,
- TR_table::FLD_TRX_ID, false);
- }
-
- switch (conds->type)
- {
- case SYSTEM_TIME_UNSPECIFIED:
- curr= newx Item_int(thd, ULONGLONG_MAX);
- cond1= newx Item_func_eq(thd, conds->field_end, curr);
- DBUG_ASSERT(!conds->start.item);
- DBUG_ASSERT(!conds->end.item);
- break;
- case SYSTEM_TIME_AS_OF:
- cond1= newx Item_func_trt_trx_sees_eq(thd, trx_id0, conds->field_start);
- cond2= newx Item_func_trt_trx_sees(thd, conds->field_end, trx_id0);
- DBUG_ASSERT(!conds->end.item);
- break;
- case SYSTEM_TIME_FROM_TO:
- cond1= newx Item_func_trt_trx_sees(thd, trx_id1, conds->field_start);
- cond2= newx Item_func_trt_trx_sees_eq(thd, conds->field_end, trx_id0);
- cond3= newx Item_func_lt(thd, conds->start.item, conds->end.item);
- break;
- case SYSTEM_TIME_BETWEEN:
- cond1= newx Item_func_trt_trx_sees_eq(thd, trx_id1, conds->field_start);
- cond2= newx Item_func_trt_trx_sees_eq(thd, conds->field_end, trx_id0);
- cond3= newx Item_func_le(thd, conds->start.item, conds->end.item);
- break;
- case SYSTEM_TIME_BEFORE:
- cond1= newx Item_func_trt_trx_sees(thd, trx_id0, conds->field_end);
- break;
- default:
- DBUG_ASSERT(0);
- }
- }
+/**
+ Setup System Versioning conditions
- if (cond1)
- {
- cond1= and_items(thd, cond2, cond1);
- cond1= and_items(thd, cond3, cond1);
- }
- return cond1;
-#undef newx
-}
+ Add WHERE condition according to FOR SYSTEM_TIME clause.
-static
-bool skip_setup_conds(THD *thd)
-{
- return (!thd->stmt_arena->is_conventional()
- && !thd->stmt_arena->is_stmt_prepare_or_first_sp_execute())
- || thd->lex->is_view_context_analysis();
-}
+ If the table is partitioned by SYSTEM_TIME and there is no FOR SYSTEM_TIME
+ clause, then select now-partition instead of modifying WHERE condition.
-Item* SELECT_LEX::period_setup_conds(THD *thd, TABLE_LIST *tables, Item *where)
+ @retval
+ -1 on error
+ @retval
+ 0 on success
+*/
+int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables)
{
- DBUG_ENTER("SELECT_LEX::period_setup_conds");
-
- if (skip_setup_conds(thd))
- DBUG_RETURN(where);
-
- Query_arena backup;
- Query_arena *arena= thd->activate_stmt_arena_if_needed(&backup);
+ DBUG_ENTER("SELECT_LEX::vers_setup_cond");
+#define newx new (thd->mem_root)
- DBUG_ASSERT(!tables->next_local && tables->table);
+ TABLE_LIST *table;
- Item *result= NULL;
- for (TABLE_LIST *table= tables; table; table= table->next_local)
+ if (!thd->stmt_arena->is_conventional() &&
+ !thd->stmt_arena->is_stmt_prepare_or_first_sp_execute())
{
- if (!table->table)
- continue;
- vers_select_conds_t &conds= table->period_conditions;
- if (!table->table->s->period.name.streq(conds.name))
- {
- my_error(ER_PERIOD_NOT_FOUND, MYF(0), conds.name.str);
- if (arena)
- thd->restore_active_arena(arena, &backup);
- DBUG_RETURN(NULL);
- }
-
- conds.period= &table->table->s->period;
- result= and_items(thd, result,
- period_get_condition(thd, table, this, &conds, true));
+ // statement is already prepared
+ DBUG_RETURN(0);
}
- result= and_items(thd, where, result);
- if (arena)
- thd->restore_active_arena(arena, &backup);
-
- DBUG_RETURN(result);
-}
-
-int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables)
-{
- DBUG_ENTER("SELECT_LEX::vers_setup_conds");
-
- if (skip_setup_conds(thd))
+ if (thd->lex->is_view_context_analysis())
DBUG_RETURN(0);
if (!versioned_tables)
{
- for (TABLE_LIST *table= tables; table; table= table->next_local)
+ for (table= tables; table; table= table->next_local)
{
if (table->table && table->table->versioned())
versioned_tables++;
@@ -966,7 +832,7 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables)
}
}
- for (TABLE_LIST *table= tables; table; table= table->next_local)
+ for (table= tables; table; table= table->next_local)
{
if (!table->table || !table->table->versioned())
continue;
@@ -974,12 +840,13 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables)
vers_select_conds_t &vers_conditions= table->vers_conditions;
#ifdef WITH_PARTITION_STORAGE_ENGINE
- /*
- if the history is stored in partitions, then partitions
- themselves are not versioned
- */
- if (table->partition_names && table->table->part_info->vers_info)
+ Vers_part_info *vers_info;
+ if (table->table->part_info && (vers_info= table->table->part_info->vers_info))
+ {
+ if (table->partition_names)
{
+ /* If the history is stored in partitions, then partitions
+ themselves are not versioned. */
if (vers_conditions.is_set())
{
my_error(ER_VERS_QUERY_IN_PARTITION, MYF(0), table->alias.str);
@@ -988,6 +855,16 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables)
else
vers_conditions.init(SYSTEM_TIME_ALL);
}
+ else if (!vers_conditions.is_set())
+ {
+ table->partition_names= newx List<String>;
+ String *s= newx String(vers_info->now_part->partition_name,
+ system_charset_info);
+ table->partition_names->push_back(s);
+ table->table->file->change_partitions_to_open(table->partition_names);
+ vers_conditions.init(SYSTEM_TIME_ALL);
+ }
+ }
#endif
if (outer_table && !vers_conditions.is_set())
@@ -1012,6 +889,16 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables)
lock_type= TL_READ; // ignore TL_WRITE, history is immutable anyway
}
+ const LEX_CSTRING *fstart=
+ thd->make_clex_string(table->table->vers_start_field()->field_name);
+ const LEX_CSTRING *fend=
+ thd->make_clex_string(table->table->vers_end_field()->field_name);
+
+ Item *row_start=
+ newx Item_field(thd, &this->context, table->db.str, table->alias.str, fstart);
+ Item *row_end=
+ newx Item_field(thd, &this->context, table->db.str, table->alias.str, fend);
+
bool timestamps_only= table->table->versioned(VERS_TIMESTAMP);
if (vers_conditions.is_set())
@@ -1031,17 +918,103 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables)
}
}
- vers_conditions.period = &table->table->s->vers;
- Item *cond= period_get_condition(thd, table, this, &vers_conditions,
- timestamps_only);
- if (cond)
- table->on_expr= and_items(thd, table->on_expr, cond);
- table->vers_conditions.type= SYSTEM_TIME_ALL;
+ Item *cond1= NULL, *cond2= NULL, *cond3= NULL, *curr= NULL;
+ Item *point_in_time1= vers_conditions.start.item;
+ Item *point_in_time2= vers_conditions.end.item;
+ TABLE *t= table->table;
+ if (t->versioned(VERS_TIMESTAMP))
+ {
+ MYSQL_TIME max_time;
+ switch (vers_conditions.type)
+ {
+ case SYSTEM_TIME_UNSPECIFIED:
+ thd->variables.time_zone->gmt_sec_to_TIME(&max_time, TIMESTAMP_MAX_VALUE);
+ max_time.second_part= TIME_MAX_SECOND_PART;
+ curr= newx Item_datetime_literal(thd, &max_time, TIME_SECOND_PART_DIGITS);
+ cond1= newx Item_func_eq(thd, row_end, curr);
+ break;
+ case SYSTEM_TIME_AS_OF:
+ cond1= newx Item_func_le(thd, row_start, point_in_time1);
+ cond2= newx Item_func_gt(thd, row_end, point_in_time1);
+ break;
+ case SYSTEM_TIME_FROM_TO:
+ cond1= newx Item_func_lt(thd, row_start, point_in_time2);
+ cond2= newx Item_func_gt(thd, row_end, point_in_time1);
+ cond3= newx Item_func_lt(thd, point_in_time1, point_in_time2);
+ break;
+ case SYSTEM_TIME_BETWEEN:
+ cond1= newx Item_func_le(thd, row_start, point_in_time2);
+ cond2= newx Item_func_gt(thd, row_end, point_in_time1);
+ cond3= newx Item_func_le(thd, point_in_time1, point_in_time2);
+ break;
+ case SYSTEM_TIME_BEFORE:
+ cond1= newx Item_func_lt(thd, row_end, point_in_time1);
+ break;
+ default:
+ DBUG_ASSERT(0);
+ }
+ }
+ else
+ {
+ DBUG_ASSERT(table->table->s && table->table->s->db_plugin);
+
+ Item *trx_id0, *trx_id1;
+
+ switch (vers_conditions.type)
+ {
+ case SYSTEM_TIME_UNSPECIFIED:
+ curr= newx Item_int(thd, ULONGLONG_MAX);
+ cond1= newx Item_func_eq(thd, row_end, curr);
+ break;
+ case SYSTEM_TIME_AS_OF:
+ trx_id0= vers_conditions.start.unit == VERS_TIMESTAMP
+ ? newx Item_func_trt_id(thd, point_in_time1, TR_table::FLD_TRX_ID)
+ : point_in_time1;
+ cond1= newx Item_func_trt_trx_sees_eq(thd, trx_id0, row_start);
+ cond2= newx Item_func_trt_trx_sees(thd, row_end, trx_id0);
+ break;
+ case SYSTEM_TIME_FROM_TO:
+ cond3= newx Item_func_lt(thd, point_in_time1, point_in_time2);
+ /* fall through */
+ case SYSTEM_TIME_BETWEEN:
+ trx_id0= vers_conditions.start.unit == VERS_TIMESTAMP
+ ? newx Item_func_trt_id(thd, point_in_time1, TR_table::FLD_TRX_ID, true)
+ : point_in_time1;
+ trx_id1= vers_conditions.end.unit == VERS_TIMESTAMP
+ ? newx Item_func_trt_id(thd, point_in_time2, TR_table::FLD_TRX_ID, false)
+ : point_in_time2;
+ cond1= vers_conditions.type == SYSTEM_TIME_FROM_TO
+ ? newx Item_func_trt_trx_sees(thd, trx_id1, row_start)
+ : newx Item_func_trt_trx_sees_eq(thd, trx_id1, row_start);
+ cond2= newx Item_func_trt_trx_sees_eq(thd, row_end, trx_id0);
+ if (!cond3)
+ cond3= newx Item_func_le(thd, point_in_time1, point_in_time2);
+ break;
+ case SYSTEM_TIME_BEFORE:
+ trx_id0= vers_conditions.start.unit == VERS_TIMESTAMP
+ ? newx Item_func_trt_id(thd, point_in_time1, TR_table::FLD_TRX_ID, true)
+ : point_in_time1;
+ cond1= newx Item_func_trt_trx_sees(thd, trx_id0, row_end);
+ break;
+ default:
+ DBUG_ASSERT(0);
+ }
+ }
+ if (cond1)
+ {
+ cond1= and_items(thd, cond2, cond1);
+ cond1= and_items(thd, cond3, cond1);
+ table->on_expr= and_items(thd, table->on_expr, cond1);
+ }
+
+ table->vers_conditions.type= SYSTEM_TIME_ALL;
} // for (table= tables; ...)
DBUG_RETURN(0);
+#undef newx
}
+#undef newx
/*****************************************************************************
Check fields, find best join, do the select and output fields.
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index c8cd423a84c..a16e47b902c 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -5278,7 +5278,7 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
err:
/* In RBR we don't need to log CREATE TEMPORARY TABLE */
- if (thd->is_current_stmt_binlog_format_row() && create_info->tmp_table())
+ if (!result && thd->is_current_stmt_binlog_format_row() && create_info->tmp_table())
DBUG_RETURN(result);
if (create_info->tmp_table())
@@ -7943,10 +7943,12 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
KEY *key_info=table->key_info;
bool rc= TRUE;
bool modified_primary_key= FALSE;
+ bool vers_system_invisible= false;
Create_field *def;
Field **f_ptr,*field;
MY_BITMAP *dropped_fields= NULL; // if it's NULL - no dropped fields
bool drop_period= false;
+ bool save_reopen= table->m_needs_reopen;
DBUG_ENTER("mysql_prepare_alter_table");
/*
@@ -8052,7 +8054,11 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
bitmap_set_bit(dropped_fields, field->field_index);
continue;
}
-
+ if (field->invisible == INVISIBLE_SYSTEM &&
+ field->flags & VERS_SYSTEM_FIELD)
+ {
+ vers_system_invisible= true;
+ }
/* invisible versioning column is dropped automatically on DROP SYSTEM VERSIONING */
if (!drop && field->invisible >= INVISIBLE_SYSTEM &&
field->flags & VERS_SYSTEM_FIELD &&
@@ -8170,7 +8176,8 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
dropped_sys_vers_fields &= VERS_SYSTEM_FIELD;
if ((dropped_sys_vers_fields ||
alter_info->flags & ALTER_DROP_PERIOD) &&
- dropped_sys_vers_fields != VERS_SYSTEM_FIELD)
+ dropped_sys_vers_fields != VERS_SYSTEM_FIELD &&
+ !vers_system_invisible)
{
StringBuffer<NAME_LEN*3> tmp;
append_drop_column(thd, dropped_sys_vers_fields & VERS_SYS_START_FLAG,
@@ -8180,6 +8187,11 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
my_error(ER_MISSING, MYF(0), table->s->table_name.str, tmp.c_ptr());
goto err;
}
+ else if (alter_info->flags & ALTER_DROP_PERIOD && vers_system_invisible)
+ {
+ my_error(ER_VERS_NO_PERIOD, MYF(0), table->s->table_name.str);
+ goto err;
+ }
alter_info->flags &= ~(ALTER_DROP_PERIOD | ALTER_ADD_PERIOD);
def_it.rewind();
while ((def=def_it++)) // Add new columns
@@ -8687,7 +8699,9 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
alter_info->create_list.swap(new_create_list);
alter_info->key_list.swap(new_key_list);
alter_info->check_constraint_list.swap(new_constraint_list);
+ DBUG_RETURN(rc);
err:
+ table->m_needs_reopen= save_reopen;
DBUG_RETURN(rc);
}
@@ -10345,6 +10359,7 @@ end_temporary:
(ulong) (copied + deleted), (ulong) deleted,
(ulong) thd->get_stmt_da()->current_statement_warn_count());
my_ok(thd, copied + deleted, 0L, alter_ctx.tmp_buff);
+ DEBUG_SYNC(thd, "alter_table_inplace_trans_commit");
DBUG_RETURN(false);
err_new_table_cleanup:
@@ -10411,7 +10426,8 @@ err_with_mdl:
tables and release the exclusive metadata lock.
*/
thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0);
- thd->mdl_context.release_all_locks_for_name(mdl_ticket);
+ if (!table_list->table)
+ thd->mdl_context.release_all_locks_for_name(mdl_ticket);
DBUG_RETURN(true);
}
@@ -10444,12 +10460,14 @@ bool mysql_trans_commit_alter_copy_data(THD *thd)
uint save_unsafe_rollback_flags;
DBUG_ENTER("mysql_trans_commit_alter_copy_data");
- /* Save flags as transcommit_implicit_are_deleting_them */
+ /* Save flags as trans_commit_implicit are deleting them */
save_unsafe_rollback_flags= thd->transaction.stmt.m_unsafe_rollback_flags;
+ DEBUG_SYNC(thd, "alter_table_copy_trans_commit");
+
if (ha_enable_transaction(thd, TRUE))
DBUG_RETURN(TRUE);
-
+
/*
Ensure that the new table is saved properly to disk before installing
the new .frm.
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index bd4277e7fea..9cf1bdd5e3e 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -7269,6 +7269,11 @@ serial_attribute:
{
Lex->last_field->versioning= $1;
Lex->create_info.options|= HA_VERSIONED_TABLE;
+ if (Lex->alter_info.flags & ALTER_DROP_SYSTEM_VERSIONING)
+ {
+ my_yyabort_error((ER_VERS_NOT_VERSIONED, MYF(0),
+ Lex->create_last_non_select_table->table_name.str));
+ }
}
;
@@ -8462,6 +8467,7 @@ alter_list_item:
| DROP SYSTEM VERSIONING_SYM
{
Lex->alter_info.flags|= ALTER_DROP_SYSTEM_VERSIONING;
+ Lex->create_info.options&= ~HA_VERSIONED_TABLE;
}
| DROP PERIOD_SYM FOR_SYSTEM_TIME_SYM
{
diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy
index a19f8d85a9e..e04554d4e88 100644
--- a/sql/sql_yacc_ora.yy
+++ b/sql/sql_yacc_ora.yy
@@ -7357,6 +7357,11 @@ serial_attribute:
{
Lex->last_field->versioning= $1;
Lex->create_info.options|= HA_VERSIONED_TABLE;
+ if (Lex->alter_info.flags & ALTER_DROP_SYSTEM_VERSIONING)
+ {
+ my_yyabort_error((ER_VERS_NOT_VERSIONED, MYF(0),
+ Lex->create_last_non_select_table->table_name.str));
+ }
}
;
@@ -8563,6 +8568,7 @@ alter_list_item:
| DROP SYSTEM VERSIONING_SYM
{
Lex->alter_info.flags|= ALTER_DROP_SYSTEM_VERSIONING;
+ Lex->create_info.options&= ~HA_VERSIONED_TABLE;
}
| DROP PERIOD_SYM FOR_SYSTEM_TIME_SYM
{
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc
index 0637b4db7df..74a28c4724f 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -212,7 +212,19 @@ static PSI_file_info wsrep_files[]=
{
{ &key_file_wsrep_gra_log, "wsrep_gra_log", 0}
};
-#endif
+
+PSI_thread_key key_wsrep_sst_joiner, key_wsrep_sst_donor,
+ key_wsrep_rollbacker, key_wsrep_applier;
+
+static PSI_thread_info wsrep_threads[]=
+{
+ {&key_wsrep_sst_joiner, "wsrep_sst_joiner_thread", PSI_FLAG_GLOBAL},
+ {&key_wsrep_sst_donor, "wsrep_sst_donor_thread", PSI_FLAG_GLOBAL},
+ {&key_wsrep_rollbacker, "wsrep_rollbacker_thread", PSI_FLAG_GLOBAL},
+ {&key_wsrep_applier, "wsrep_applier_thread", PSI_FLAG_GLOBAL}
+};
+
+#endif /* HAVE_PSI_INTERFACE */
my_bool wsrep_inited= 0; // initialized ?
@@ -759,6 +771,7 @@ void wsrep_thr_init()
mysql_mutex_register("sql", wsrep_mutexes, array_elements(wsrep_mutexes));
mysql_cond_register("sql", wsrep_conds, array_elements(wsrep_conds));
mysql_file_register("sql", wsrep_files, array_elements(wsrep_files));
+ mysql_thread_register("sql", wsrep_threads, array_elements(wsrep_threads));
#endif
mysql_mutex_init(key_LOCK_wsrep_ready, &LOCK_wsrep_ready, MY_MUTEX_INIT_FAST);
diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h
index 844437bab95..a7a71307fdb 100644
--- a/sql/wsrep_mysqld.h
+++ b/sql/wsrep_mysqld.h
@@ -341,7 +341,14 @@ extern PSI_mutex_key key_LOCK_wsrep_thd_queue;
extern PSI_cond_key key_COND_wsrep_thd_queue;
extern PSI_file_key key_file_wsrep_gra_log;
+
+extern PSI_thread_key key_wsrep_sst_joiner;
+extern PSI_thread_key key_wsrep_sst_donor;
+extern PSI_thread_key key_wsrep_rollbacker;
+extern PSI_thread_key key_wsrep_applier;
#endif /* HAVE_PSI_INTERFACE */
+
+
struct TABLE_LIST;
class Alter_info;
int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_,
@@ -418,6 +425,8 @@ class Wsrep_thd_args
enum wsrep_thread_type thread_type() {return thread_type_;}
+ pthread_t thread_id;
+
private:
Wsrep_thd_args(const Wsrep_thd_args&);
diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc
index 3181415dad1..85d5aca342d 100644
--- a/sql/wsrep_sst.cc
+++ b/sql/wsrep_sst.cc
@@ -663,10 +663,10 @@ static ssize_t sst_prepare_other (const char* method,
pthread_t tmp;
sst_thread_arg arg(cmd_str(), env());
mysql_mutex_lock (&arg.lock);
- ret= pthread_create (&tmp, NULL, sst_joiner_thread, &arg);
+ ret = mysql_thread_create (key_wsrep_sst_joiner, &tmp, NULL, sst_joiner_thread, &arg);
if (ret)
{
- WSREP_ERROR("sst_prepare_other(): pthread_create() failed: %d (%s)",
+ WSREP_ERROR("sst_prepare_other(): mysql_thread_create() failed: %d (%s)",
ret, strerror(ret));
return -ret;
}
@@ -1350,10 +1350,10 @@ static int sst_donate_other (const char* method,
pthread_t tmp;
sst_thread_arg arg(cmd_str(), env);
mysql_mutex_lock (&arg.lock);
- ret= pthread_create (&tmp, NULL, sst_donor_thread, &arg);
+ ret = mysql_thread_create (key_wsrep_sst_donor, &tmp, NULL, sst_donor_thread, &arg);
if (ret)
{
- WSREP_ERROR("sst_donate_other(): pthread_create() failed: %d (%s)",
+ WSREP_ERROR("sst_donate_other(): mysql_thread_create() failed: %d (%s)",
ret, strerror(ret));
return ret;
}
diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc
index c62132b16a2..80ffe67b405 100644
--- a/sql/wsrep_thd.cc
+++ b/sql/wsrep_thd.cc
@@ -86,10 +86,25 @@ static void wsrep_replication_process(THD *thd,
static bool create_wsrep_THD(Wsrep_thd_args* args)
{
ulong old_wsrep_running_threads= wsrep_running_threads;
- pthread_t unused;
+#ifdef HAVE_PSI_THREAD_INTERFACE
+ PSI_thread_key key;
- bool res= pthread_create(&unused, &connection_attrib, start_wsrep_THD,
- args);
+ switch (args->thread_type())
+ {
+ case WSREP_APPLIER_THREAD:
+ key= key_wsrep_applier;
+ break;
+ case WSREP_ROLLBACKER_THREAD:
+ key= key_wsrep_rollbacker;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+#endif
+
+ bool res= mysql_thread_create(key, &args->thread_id, &connection_attrib, start_wsrep_THD,
+ (void*)args);
/*
if starting a thread on server startup, wait until the this thread's THD
is fully initialized (otherwise a THD initialization code might