summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2022-05-08 15:02:19 +0200
committerSergei Golubchik <serg@mariadb.org>2022-05-08 23:03:08 +0200
commita70a1cf3f4ed10c9d9194b2b8df6b6f08551a937 (patch)
tree517124ec5059f48bff1e02b934355e8162183efc /sql
parent40b8f3ec1a76fc23eb6bf9c5a8fef1debcbf5843 (diff)
parent79660e59ee8fcd23f928c72dc77682b875bd58ce (diff)
downloadmariadb-git-a70a1cf3f4ed10c9d9194b2b8df6b6f08551a937.tar.gz
Merge branch '10.3' into 10.4
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc7
-rw-r--r--sql/ha_partition.cc16
-rw-r--r--sql/handler.cc3
-rw-r--r--sql/item.cc13
-rw-r--r--sql/item.h28
-rw-r--r--sql/item_func.cc2
-rw-r--r--sql/item_subselect.cc26
-rw-r--r--sql/item_sum.cc6
-rw-r--r--sql/partition_info.cc61
-rw-r--r--sql/partition_info.h6
-rw-r--r--sql/rpl_gtid.h1
-rw-r--r--sql/slave.cc165
-rw-r--r--sql/sp_cache.cc9
-rw-r--r--sql/sp_head.cc2
-rw-r--r--sql/sql_base.cc7
-rw-r--r--sql/sql_class.cc108
-rw-r--r--sql/sql_class.h65
-rw-r--r--sql/sql_expression_cache.cc4
-rw-r--r--sql/sql_expression_cache.h5
-rw-r--r--sql/sql_handler.cc4
-rw-r--r--sql/sql_insert.cc9
-rw-r--r--sql/sql_lex.cc28
-rw-r--r--sql/sql_lex.h23
-rw-r--r--sql/sql_parse.cc2
-rw-r--r--sql/sql_plugin.cc3
-rw-r--r--sql/sql_select.cc13
-rw-r--r--sql/sql_select.h4
-rw-r--r--sql/sql_show.cc32
-rw-r--r--sql/sql_table.cc13
-rw-r--r--sql/sql_type.cc1
-rw-r--r--sql/sql_window.cc68
-rw-r--r--sql/sql_window.h15
-rw-r--r--sql/sql_yacc.yy18
-rw-r--r--sql/sql_yacc_ora.yy14
-rw-r--r--sql/table.cc38
-rw-r--r--sql/tztime.cc6
36 files changed, 609 insertions, 216 deletions
diff --git a/sql/field.cc b/sql/field.cc
index 7d34054a4a2..b5f7e468d46 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -3207,11 +3207,12 @@ Field_new_decimal::Field_new_decimal(uchar *ptr_arg,
uint8 dec_arg,bool zero_arg,
bool unsigned_arg)
:Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
- unireg_check_arg, field_name_arg, dec_arg, zero_arg, unsigned_arg)
+ unireg_check_arg, field_name_arg,
+ MY_MIN(dec_arg, DECIMAL_MAX_SCALE), zero_arg, unsigned_arg)
{
precision= get_decimal_precision(len_arg, dec_arg, unsigned_arg);
- DBUG_ASSERT((precision <= DECIMAL_MAX_PRECISION) &&
- (dec <= DECIMAL_MAX_SCALE));
+ DBUG_ASSERT(precision <= DECIMAL_MAX_PRECISION);
+ DBUG_ASSERT(dec <= DECIMAL_MAX_SCALE);
bin_size= my_decimal_get_binary_size(precision, dec);
}
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 0fcf966f71b..bf430a00f18 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -4012,6 +4012,8 @@ int ha_partition::external_lock(THD *thd, int lock_type)
if (lock_type == F_UNLCK)
{
bitmap_clear_all(used_partitions);
+ if (m_lock_type == F_WRLCK && m_part_info->vers_require_hist_part(thd))
+ m_part_info->vers_check_limit(thd);
}
else
{
@@ -4032,13 +4034,7 @@ int ha_partition::external_lock(THD *thd, int lock_type)
{
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 &&
- /* TODO: MDEV-20345 exclude more inapproriate commands like INSERT
- These commands may be excluded because working history partition is needed
- only for versioned DML. */
- thd->lex->sql_command != SQLCOM_SELECT &&
- thd->lex->sql_command != SQLCOM_INSERT_SELECT &&
- (error= m_part_info->vers_set_hist_part(thd)))
+ if ((error= m_part_info->vers_set_hist_part(thd)))
goto err_handler;
}
DBUG_RETURN(0);
@@ -4191,11 +4187,7 @@ int ha_partition::start_stmt(THD *thd, thr_lock_type lock_type)
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 &&
- // TODO: MDEV-20345 (see above)
- thd->lex->sql_command != SQLCOM_SELECT &&
- thd->lex->sql_command != SQLCOM_INSERT_SELECT)
- error= m_part_info->vers_set_hist_part(thd);
+ error= m_part_info->vers_set_hist_part(thd);
default:;
}
DBUG_RETURN(error);
diff --git a/sql/handler.cc b/sql/handler.cc
index 22f5aa4e7e7..4092ee99e0b 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -5182,6 +5182,9 @@ int handler::calculate_checksum()
for (uint i= 0; i < table->s->fields; i++ )
{
Field *f= table->field[i];
+ if (!f->stored_in_db())
+ continue;
+
if (! thd->variables.old_mode && f->is_real_null(0))
{
diff --git a/sql/item.cc b/sql/item.cc
index 4c699bb974d..a791d5bf8ca 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -924,8 +924,7 @@ bool Item_field::check_field_expression_processor(void *arg)
(!field->vcol_info && !org_field->vcol_info)) &&
field->field_index >= org_field->field_index))
{
- my_error(ER_EXPRESSION_REFERS_TO_UNINIT_FIELD,
- MYF(0),
+ my_error(ER_EXPRESSION_REFERS_TO_UNINIT_FIELD, MYF(0),
org_field->field_name.str, field->field_name.str);
return 1;
}
@@ -9377,6 +9376,12 @@ bool Item_default_value::eq(const Item *item, bool binary_cmp) const
}
+bool Item_default_value::check_field_expression_processor(void *)
+{
+ field->default_value= ((Item_field *)(arg->real_item()))->field->default_value;
+ return 0;
+}
+
bool Item_default_value::fix_fields(THD *thd, Item **items)
{
Item *real_arg;
@@ -9418,7 +9423,6 @@ bool Item_default_value::fix_fields(THD *thd, Item **items)
}
if (!(def_field= (Field*) thd->alloc(field_arg->field->size_of())))
goto error;
- cached_field= def_field;
memcpy((void *)def_field, (void *)field_arg->field,
field_arg->field->size_of());
def_field->reset_fields();
@@ -9447,8 +9451,7 @@ error:
void Item_default_value::cleanup()
{
- delete cached_field; // Free cached blob data
- cached_field= 0;
+ delete field; // Free cached blob data
Item_field::cleanup();
}
diff --git a/sql/item.h b/sql/item.h
index af6f350216d..f074ea1e3da 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -6457,12 +6457,11 @@ class Item_default_value : public Item_field
void calculate();
public:
Item *arg;
- Field *cached_field;
Item_default_value(THD *thd, Name_resolution_context *context_arg, Item *a,
bool vcol_assignment_arg)
:Item_field(thd, context_arg, (const char *)NULL, (const char *)NULL,
&null_clex_str), vcol_assignment_ok(vcol_assignment_arg),
- arg(a), cached_field(NULL) {}
+ arg(a) {}
enum Type type() const { return DEFAULT_VALUE_ITEM; }
bool eq(const Item *item, bool binary_cmp) const;
bool fix_fields(THD *, Item **);
@@ -6475,6 +6474,10 @@ public:
bool get_date(THD *thd, MYSQL_TIME *ltime,date_mode_t fuzzydate);
bool val_native(THD *thd, Native *to);
bool val_native_result(THD *thd, Native *to);
+ longlong val_datetime_packed(THD *thd)
+ { return Item::val_datetime_packed(thd); }
+ longlong val_time_packed(THD *thd)
+ { return Item::val_time_packed(thd); }
/* Result variants */
double val_result();
@@ -6495,16 +6498,16 @@ public:
return false;
}
table_map used_tables() const;
- virtual void update_used_tables()
+ void update_used_tables()
{
if (field && field->default_value)
field->default_value->expr->update_used_tables();
}
bool vcol_assignment_allowed_value() const { return vcol_assignment_ok; }
- Field *get_tmp_table_field() { return 0; }
Item *get_tmp_table_item(THD *thd) { return this; }
Item_field *field_for_view_update() { return 0; }
bool update_vcol_processor(void *arg) { return 0; }
+ bool check_field_expression_processor(void *arg);
bool check_func_default_processor(void *arg) { return true; }
bool walk(Item_processor processor, bool walk_subquery, void *args)
@@ -6782,7 +6785,7 @@ public:
for any value.
*/
-class Item_cache: public Item,
+class Item_cache: public Item_fixed_hybrid,
public Type_handler_hybrid_field_type
{
protected:
@@ -6813,7 +6816,7 @@ public:
bool null_value_inside;
Item_cache(THD *thd):
- Item(thd),
+ Item_fixed_hybrid(thd),
Type_handler_hybrid_field_type(&type_handler_string),
example(0), cached_field(0),
value_cached(0),
@@ -6822,10 +6825,11 @@ public:
maybe_null= 1;
null_value= 1;
null_value_inside= true;
+ fixed= 1;
}
protected:
Item_cache(THD *thd, const Type_handler *handler):
- Item(thd),
+ Item_fixed_hybrid(thd),
Type_handler_hybrid_field_type(handler),
example(0), cached_field(0),
value_cached(0),
@@ -6834,6 +6838,7 @@ protected:
maybe_null= 1;
null_value= 1;
null_value_inside= true;
+ fixed= 1;
}
public:
@@ -6885,10 +6890,17 @@ public:
}
return mark_unsupported_function("cache", arg, VCOL_IMPOSSIBLE);
}
+ bool fix_fields(THD *thd, Item **ref)
+ {
+ fixed= 1;
+ if (example && !example->is_fixed())
+ return example->fix_fields(thd, ref);
+ return 0;
+ }
void cleanup()
{
clear();
- Item::cleanup();
+ Item_fixed_hybrid::cleanup();
}
/**
Check if saved item has a non-NULL value.
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 1660652001c..935208423a4 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -2447,7 +2447,7 @@ void Item_func_round::fix_arg_decimal()
set_handler(&type_handler_newdecimal);
unsigned_flag= args[0]->unsigned_flag;
decimals= args[0]->decimals;
- max_length= float_length(args[0]->decimals) + 1;
+ max_length= args[0]->max_length;
}
}
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index d19e89ad6af..50b8d9192c5 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -773,6 +773,7 @@ bool Item_subselect::exec()
DBUG_ENTER("Item_subselect::exec");
DBUG_ASSERT(fixed);
+ DBUG_ASSERT(!eliminated);
DBUG_EXECUTE_IF("Item_subselect",
Item::Print print(this,
@@ -1282,11 +1283,18 @@ bool Item_singlerow_subselect::fix_length_and_dec()
}
unsigned_flag= value->unsigned_flag;
/*
- If there are not tables in subquery then ability to have NULL value
- depends on SELECT list (if single row subquery have tables then it
- always can be NULL if there are not records fetched).
+ If the subquery has no tables (1) and is not a UNION (2), like:
+
+ (SELECT subq_value)
+
+ then its NULLability is the same as subq_value's NULLability.
+
+ (1): A subquery that uses a table will return NULL when the table is empty.
+ (2): A UNION subquery will return NULL if it produces a "Subquery returns
+ more than one row" error.
*/
- if (engine->no_tables())
+ if (engine->no_tables() &&
+ engine->engine_type() != subselect_engine::UNION_ENGINE)
maybe_null= engine->may_be_null();
else
{
@@ -1322,6 +1330,16 @@ Item* Item_singlerow_subselect::expr_cache_insert_transformer(THD *tmp_thd,
DBUG_ASSERT(thd == tmp_thd);
+ /*
+ Do not create subquery cache if the subquery was eliminated.
+ The optimizer may eliminate subquery items (see
+ eliminate_subselect_processor). However it does not update
+ all query's data structures, so the eliminated item may be
+ still reachable.
+ */
+ if (eliminated)
+ DBUG_RETURN(this);
+
if (expr_cache)
DBUG_RETURN(expr_cache);
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 8098d1aa5e0..f80b89bc828 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -1540,6 +1540,8 @@ void Item_sum_sum::fix_length_and_dec_decimal()
decimals= args[0]->decimals;
/* SUM result can't be longer than length(arg) + length(MAX_ROWS) */
int precision= args[0]->decimal_precision() + DECIMAL_LONGLONG_DIGITS;
+ decimals= MY_MIN(decimals, DECIMAL_MAX_SCALE);
+ precision= MY_MIN(precision, DECIMAL_MAX_PRECISION);
max_length= my_decimal_precision_to_length_no_truncation(precision,
decimals,
unsigned_flag);
@@ -1950,12 +1952,12 @@ void Item_sum_avg::fix_length_and_dec_decimal()
{
Item_sum_sum::fix_length_and_dec_decimal();
int precision= args[0]->decimal_precision() + prec_increment;
- decimals= MY_MIN(args[0]->decimals + prec_increment, DECIMAL_MAX_SCALE);
+ decimals= MY_MIN(args[0]->decimal_scale() + prec_increment, DECIMAL_MAX_SCALE);
max_length= my_decimal_precision_to_length_no_truncation(precision,
decimals,
unsigned_flag);
f_precision= MY_MIN(precision+DECIMAL_LONGLONG_DIGITS, DECIMAL_MAX_PRECISION);
- f_scale= args[0]->decimals;
+ f_scale= args[0]->decimal_scale();
dec_bin_size= my_decimal_get_binary_size(f_precision, f_scale);
}
diff --git a/sql/partition_info.cc b/sql/partition_info.cc
index edcdd6d2b37..90ef388f3b9 100644
--- a/sql/partition_info.cc
+++ b/sql/partition_info.cc
@@ -835,6 +835,9 @@ bool partition_info::has_unique_name(partition_element *element)
int partition_info::vers_set_hist_part(THD *thd)
{
+ if (!vers_require_hist_part(thd))
+ return 0;
+
if (table->pos_in_table_list &&
table->pos_in_table_list->partition_names)
{
@@ -843,12 +846,10 @@ int partition_info::vers_set_hist_part(THD *thd)
if (vers_info->limit)
{
ha_partition *hp= (ha_partition*)(table->file);
- partition_element *next= NULL;
+ partition_element *next;
List_iterator<partition_element> it(partitions);
- while (next != vers_info->hist_part)
- next= it++;
- DBUG_ASSERT(bitmap_is_set(&read_partitions, next->id));
- ha_rows records= hp->part_records(next);
+ ha_rows records= 0;
+ vers_info->hist_part= partitions.head();
while ((next= it++) != vers_info->now_part)
{
DBUG_ASSERT(bitmap_is_set(&read_partitions, next->id));
@@ -858,12 +859,8 @@ int partition_info::vers_set_hist_part(THD *thd)
vers_info->hist_part= next;
records= next_records;
}
- if (records > vers_info->limit)
- {
- if (next == vers_info->now_part)
- goto warn;
+ if (records >= vers_info->limit && next != vers_info->now_part)
vers_info->hist_part= next;
- }
return 0;
}
@@ -885,11 +882,45 @@ int partition_info::vers_set_hist_part(THD *thd)
}
}
return 0;
-warn:
- my_error(WARN_VERS_PART_FULL, MYF(ME_WARNING|ME_ERROR_LOG),
- table->s->db.str, table->s->table_name.str,
- vers_info->hist_part->partition_name);
- return 0;
+}
+
+
+/**
+ Warn at the end of DML command if the last history partition is out of LIMIT.
+*/
+void partition_info::vers_check_limit(THD *thd)
+{
+ if (!vers_info->limit ||
+ vers_info->hist_part->id + 1 < vers_info->now_part->id)
+ return;
+
+ /*
+ NOTE: at this point read_partitions bitmap is already pruned by DML code,
+ we have to set read bits for working history partition. We could use
+ bitmap_set_all(), but this is not optimal since there can be quite a number
+ of partitions.
+ */
+ const uint32 sub_factor= num_subparts ? num_subparts : 1;
+ uint32 part_id= vers_info->hist_part->id * sub_factor;
+ const uint32 part_id_end= part_id + sub_factor;
+ DBUG_ASSERT(part_id_end <= num_parts * sub_factor);
+ for (; part_id < part_id_end; ++part_id)
+ bitmap_set_bit(&read_partitions, part_id);
+
+ ha_partition *hp= (ha_partition*)(table->file);
+ ha_rows hist_rows= hp->part_records(vers_info->hist_part);
+ if (hist_rows >= vers_info->limit)
+ {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ WARN_VERS_PART_FULL,
+ ER_THD(thd, WARN_VERS_PART_FULL),
+ table->s->db.str, table->s->table_name.str,
+ vers_info->hist_part->partition_name);
+
+ sql_print_warning(ER_THD(thd, WARN_VERS_PART_FULL),
+ table->s->db.str, table->s->table_name.str,
+ vers_info->hist_part->partition_name);
+ }
}
diff --git a/sql/partition_info.h b/sql/partition_info.h
index 9fb20268738..2f8b1a7fafd 100644
--- a/sql/partition_info.h
+++ b/sql/partition_info.h
@@ -421,7 +421,13 @@ public:
vers_info->limit= limit;
return !limit;
}
+ bool vers_require_hist_part(THD *thd) const
+ {
+ return part_type == VERSIONING_PARTITION &&
+ thd->lex->vers_history_generating();
+ }
int vers_set_hist_part(THD *thd);
+ void vers_check_limit(THD *thd);
bool vers_setup_expression(THD *thd, uint32 alter_add= 0); /* Stage 1. */
partition_element *get_partition(uint part_id)
{
diff --git a/sql/rpl_gtid.h b/sql/rpl_gtid.h
index b633716bfe5..081f7e309f4 100644
--- a/sql/rpl_gtid.h
+++ b/sql/rpl_gtid.h
@@ -26,6 +26,7 @@
extern const LEX_CSTRING rpl_gtid_slave_state_table_name;
class String;
+#define PARAM_GTID(G) G.domain_id, G.server_id, G.seq_no
struct rpl_gtid
{
diff --git a/sql/slave.cc b/sql/slave.cc
index 029fd0f5aaf..d0bc7e474df 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -3240,9 +3240,9 @@ static bool send_show_master_info_data(THD *thd, Master_info *mi, bool full,
protocol->store((uint32) mi->master_id);
// SQL_Delay
// Master_Ssl_Crl
- protocol->store(mi->ssl_ca, &my_charset_bin);
+ protocol->store(mi->ssl_crl, &my_charset_bin);
// Master_Ssl_Crlpath
- protocol->store(mi->ssl_capath, &my_charset_bin);
+ protocol->store(mi->ssl_crlpath, &my_charset_bin);
// Using_Gtid
protocol->store(mi->using_gtid_astext(mi->using_gtid), &my_charset_bin);
// Gtid_IO_Pos
@@ -3334,7 +3334,7 @@ bool show_all_master_info(THD* thd)
String gtid_pos;
Master_info **tmp;
List<Item> field_list;
- DBUG_ENTER("show_master_info");
+ DBUG_ENTER("show_all_master_info");
mysql_mutex_assert_owner(&LOCK_active_mi);
gtid_pos.length(0);
@@ -6615,17 +6615,75 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len)
mi->gtid_event_seen= true;
/*
- We have successfully queued to relay log everything before this GTID, so
+ Unless the previous group is malformed,
+ we have successfully queued to relay log everything before this GTID, so
in case of reconnect we can start from after any previous GTID.
- (Normally we would have updated gtid_current_pos earlier at the end of
- the previous event group, but better leave an extra check here for
- safety).
+ (We must have updated gtid_current_pos earlier at the end of
+ the previous event group. Unless ...)
*/
- if (mi->events_queued_since_last_gtid)
+ if (unlikely(mi->events_queued_since_last_gtid > 0))
{
- mi->gtid_current_pos.update(&mi->last_queued_gtid);
- mi->events_queued_since_last_gtid= 0;
+ /*
+ ...unless the last group has not been completed. An assert below
+ can be satisfied only with the strict mode that ensures
+ against "genuine" gtid duplicates.
+ */
+ rpl_gtid *gtid_in_slave_state=
+ mi->gtid_current_pos.find(mi->last_queued_gtid.domain_id);
+
+ // Slave gtid state must not have updated yet to the last received gtid.
+ DBUG_ASSERT((mi->using_gtid == Master_info::USE_GTID_NO ||
+ !opt_gtid_strict_mode) ||
+ (!gtid_in_slave_state ||
+ !(*gtid_in_slave_state == mi->last_queued_gtid)));
+
+ DBUG_EXECUTE_IF("slave_discard_xid_for_gtid_0_x_1000",
+ {
+ /* Inject an event group that is missing its XID commit event. */
+ if ((mi->last_queued_gtid.domain_id == 0 &&
+ mi->last_queued_gtid.seq_no == 1000) ||
+ (mi->last_queued_gtid.domain_id == 1 &&
+ mi->last_queued_gtid.seq_no == 32))
+ {
+ sql_print_warning(
+ "Unexpected break of being relay-logged GTID %u-%u-%llu "
+ "event group by the current GTID event %u-%u-%llu",
+ PARAM_GTID(mi->last_queued_gtid),PARAM_GTID(event_gtid));
+ DBUG_SET("-d,slave_discard_xid_for_gtid_0_x_1000");
+ goto dbug_gtid_accept;
+ }
+ });
+ error= ER_SLAVE_RELAY_LOG_WRITE_FAILURE;
+ sql_print_error("Unexpected break of being relay-logged GTID %u-%u-%llu "
+ "event group by the current GTID event %u-%u-%llu",
+ PARAM_GTID(mi->last_queued_gtid),PARAM_GTID(event_gtid));
+ goto err;
}
+ else if (unlikely(mi->gtid_reconnect_event_skip_count > 0))
+ {
+ if (mi->gtid_reconnect_event_skip_count ==
+ mi->events_queued_since_last_gtid)
+ {
+ DBUG_ASSERT(event_gtid == mi->last_queued_gtid);
+
+ goto default_action;
+ }
+
+ DBUG_ASSERT(0);
+ }
+ // else_likely{...
+#ifndef DBUG_OFF
+dbug_gtid_accept:
+ DBUG_EXECUTE_IF("slave_discard_gtid_0_x_1002",
+ {
+ if (mi->last_queued_gtid.server_id == 27697 &&
+ mi->last_queued_gtid.seq_no == 1002)
+ {
+ DBUG_SET("-d,slave_discard_gtid_0_x_1002");
+ goto skip_relay_logging;
+ }
+ });
+#endif
mi->last_queued_gtid= event_gtid;
mi->last_queued_gtid_standalone=
(gtid_flag & Gtid_log_event::FL_STANDALONE) != 0;
@@ -6635,6 +6693,7 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len)
++mi->events_queued_since_last_gtid;
inc_pos= event_len;
+ // ...} eof else_likely
}
break;
/*
@@ -6713,6 +6772,12 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len)
case XID_EVENT:
DBUG_EXECUTE_IF("slave_discard_xid_for_gtid_0_x_1000",
{
+ if (mi->last_queued_gtid.server_id == 27697 &&
+ mi->last_queued_gtid.seq_no == 1000)
+ {
+ DBUG_SET("-d,slave_discard_xid_for_gtid_0_x_1000");
+ goto skip_relay_logging;
+ }
/* Inject an event group that is missing its XID commit event. */
if (mi->last_queued_gtid.domain_id == 0 &&
mi->last_queued_gtid.seq_no == 1000)
@@ -6758,15 +6823,48 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len)
}
};);
- if (mi->using_gtid != Master_info::USE_GTID_NO && mi->gtid_event_seen)
+ if (mi->using_gtid != Master_info::USE_GTID_NO)
{
- if (unlikely(mi->gtid_reconnect_event_skip_count))
+ if (likely(mi->gtid_event_seen))
{
- --mi->gtid_reconnect_event_skip_count;
- gtid_skip_enqueue= true;
+ if (unlikely(mi->gtid_reconnect_event_skip_count))
+ {
+ if (!got_gtid_event &&
+ mi->gtid_reconnect_event_skip_count ==
+ mi->events_queued_since_last_gtid)
+ goto gtid_not_start; // the 1st re-sent must be gtid
+
+ --mi->gtid_reconnect_event_skip_count;
+ gtid_skip_enqueue= true;
+ }
+ else if (likely(mi->events_queued_since_last_gtid))
+ {
+ DBUG_ASSERT(!got_gtid_event);
+
+ ++mi->events_queued_since_last_gtid;
+ }
+ else if (Log_event::is_group_event((Log_event_type) (uchar)
+ buf[EVENT_TYPE_OFFSET]))
+ {
+ goto gtid_not_start; // no first gtid event in this group
+ }
+ }
+ else if (Log_event::is_group_event((Log_event_type) (uchar)
+ buf[EVENT_TYPE_OFFSET]))
+ {
+ gtid_not_start:
+
+ DBUG_ASSERT(!got_gtid_event);
+
+ error= ER_SLAVE_RELAY_LOG_WRITE_FAILURE;
+ sql_print_error("The current group of events starts with "
+ "a non-GTID %s event; "
+ "the last seen GTID is %u-%u-%llu",
+ Log_event::get_type_str((Log_event_type) (uchar)
+ buf[EVENT_TYPE_OFFSET]),
+ mi->last_queued_gtid);
+ goto err;
}
- else if (mi->events_queued_since_last_gtid)
- ++mi->events_queued_since_last_gtid;
}
if (!is_compress_event)
@@ -6959,11 +7057,13 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len)
The whole of the current event group is queued. So in case of
reconnect we can start from after the current GTID.
*/
- if (mi->gtid_reconnect_event_skip_count)
+ if (gtid_skip_enqueue)
{
bool first= true;
StringBuffer<1024> gtid_text;
+ DBUG_ASSERT(mi->events_queued_since_last_gtid > 1);
+
rpl_slave_state_tostring_helper(&gtid_text, &mi->last_queued_gtid,
&first);
sql_print_error("Slave IO thread received a terminal event from "
@@ -6973,12 +7073,39 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len)
gtid_text.ptr(),
mi->gtid_reconnect_event_skip_count,
mi->events_queued_since_last_gtid);
+ error= ER_SLAVE_RELAY_LOG_WRITE_FAILURE;
+ goto err;
}
mi->gtid_current_pos.update(&mi->last_queued_gtid);
mi->events_queued_since_last_gtid= 0;
- /* Reset the domain_id_filter flag. */
- mi->domain_id_filter.reset_filter();
+ if (unlikely(gtid_skip_enqueue))
+ {
+ error= ER_SLAVE_RELAY_LOG_WRITE_FAILURE;
+ sql_print_error("Recieved a group closing %s event "
+ "at %llu position in the group while there are "
+ "still %llu events to skip upon reconnecting; "
+ "the last seen GTID is %u-%u-%llu",
+ Log_event::get_type_str((Log_event_type) (uchar)
+ buf[EVENT_TYPE_OFFSET]),
+ (mi->events_queued_since_last_gtid -
+ mi->gtid_reconnect_event_skip_count),
+ mi->events_queued_since_last_gtid,
+ mi->last_queued_gtid);
+ goto err;
+ }
+ else
+ {
+ /*
+ The whole of the current event group is queued. So in case of
+ reconnect we can start from after the current GTID.
+ */
+ mi->gtid_current_pos.update(&mi->last_queued_gtid);
+ mi->events_queued_since_last_gtid= 0;
+
+ /* Reset the domain_id_filter flag. */
+ mi->domain_id_filter.reset_filter();
+ }
}
skip_relay_logging:
diff --git a/sql/sp_cache.cc b/sql/sp_cache.cc
index e4ffbdcb155..e97f24c5487 100644
--- a/sql/sp_cache.cc
+++ b/sql/sp_cache.cc
@@ -312,3 +312,12 @@ sp_cache::cleanup()
{
my_hash_free(&m_hashtable);
}
+
+
+void Sp_caches::sp_caches_clear()
+{
+ sp_cache_clear(&sp_proc_cache);
+ sp_cache_clear(&sp_func_cache);
+ sp_cache_clear(&sp_package_spec_cache);
+ sp_cache_clear(&sp_package_body_cache);
+}
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index ab950c50251..6102769a47d 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -769,7 +769,7 @@ void
sp_head::set_stmt_end(THD *thd)
{
Lex_input_stream *lip= & thd->m_parser_state->m_lip; /* shortcut */
- const char *end_ptr= lip->get_cpp_ptr(); /* shortcut */
+ const char *end_ptr= lip->get_cpp_tok_start(); /* shortcut */
/* Make the string of parameters. */
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index ef7a075e304..42285e9b3a4 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -907,7 +907,14 @@ void close_thread_tables(THD *thd)
table->s->table_name.str, (ulong) table->query_id));
if (thd->locked_tables_mode)
+ {
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+ if (table->part_info && table->part_info->vers_require_hist_part(thd) &&
+ !thd->stmt_arena->is_stmt_prepare())
+ table->part_info->vers_check_limit(thd);
+#endif
table->vcol_cleanup_expr(thd);
+ }
/* Detach MERGE children after every statement. Even under LOCK TABLES. */
if (thd->locked_tables_mode <= LTM_LOCK_TABLES ||
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 6fb657d3c00..775f3c173ef 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2015, Oracle and/or its affiliates.
- Copyright (c) 2008, 2021, MariaDB Corporation.
+ Copyright (c) 2008, 2022, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -818,11 +818,6 @@ THD::THD(my_thread_id id, bool is_wsrep_applier)
(my_hash_get_key) get_sequence_last_key,
(my_hash_free_key) free_sequence_last, HASH_THREAD_SPECIFIC);
- sp_proc_cache= NULL;
- sp_func_cache= NULL;
- sp_package_spec_cache= NULL;
- sp_package_body_cache= NULL;
-
/* For user vars replication*/
if (opt_bin_log)
my_init_dynamic_array(&user_var_events,
@@ -1431,10 +1426,7 @@ void THD::change_user(void)
my_hash_init(&sequences, system_charset_info, SEQUENCES_HASH_SIZE, 0, 0,
(my_hash_get_key) get_sequence_last_key,
(my_hash_free_key) free_sequence_last, HASH_THREAD_SPECIFIC);
- sp_cache_clear(&sp_proc_cache);
- sp_cache_clear(&sp_func_cache);
- sp_cache_clear(&sp_package_spec_cache);
- sp_cache_clear(&sp_package_body_cache);
+ sp_caches_clear();
opt_trace.delete_traces();
}
@@ -1563,10 +1555,7 @@ void THD::cleanup(void)
my_hash_free(&user_vars);
my_hash_free(&sequences);
- sp_cache_clear(&sp_proc_cache);
- sp_cache_clear(&sp_func_cache);
- sp_cache_clear(&sp_package_spec_cache);
- sp_cache_clear(&sp_package_body_cache);
+ sp_caches_clear();
auto_inc_intervals_forced.empty();
auto_inc_intervals_in_cur_stmt_for_binlog.empty();
@@ -6420,47 +6409,84 @@ int THD::decide_logging_format(TABLE_LIST *tables)
DBUG_RETURN(0);
}
-int THD::decide_logging_format_low(TABLE *table)
+
+/*
+ Reconsider logging format in case of INSERT...ON DUPLICATE KEY UPDATE
+ for tables with more than one unique keys in case of MIXED binlog format.
+
+ Unsafe means that a master could execute the statement differently than
+ the slave.
+ This could can happen in the following cases:
+ - The unique check are done in different order on master or slave
+ (different engine or different key order).
+ - There is a conflict on another key than the first and before the
+ statement is committed, another connection commits a row that conflicts
+ on an earlier unique key. Example follows:
+
+ Below a and b are unique keys, the table has a row (1,1,0)
+ connection 1:
+ INSERT INTO t1 set a=2,b=1,c=0 ON DUPLICATE KEY UPDATE c=1;
+ connection 2:
+ INSERT INTO t1 set a=2,b=2,c=0;
+
+ If 2 commits after 1 has been executed but before 1 has committed
+ (and are thus put before the other in the binary log), one will
+ get different data on the slave:
+ (1,1,1),(2,2,1) instead of (1,1,1),(2,2,0)
+*/
+
+void THD::reconsider_logging_format_for_iodup(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)
+ DBUG_ENTER("reconsider_logging_format_for_iodup");
+ enum_binlog_format bf= (enum_binlog_format) wsrep_binlog_format();
+
+ DBUG_ASSERT(lex->duplicates == DUP_UPDATE);
+
+ if (bf <= BINLOG_FORMAT_STMT &&
+ !is_current_stmt_binlog_format_row())
{
+ KEY *end= table->s->key_info + table->s->keys;
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 (KEY *keyinfo= table->s->key_info; keyinfo < end ; keyinfo++)
+ {
+ if (keyinfo->flags & HA_NOSAME)
{
+ /*
+ We assume that the following cases will guarantee that the
+ key is unique if a key part is not set:
+ - The key part is an autoincrement (autogenerated)
+ - The key part has a default value that is null and it not
+ a virtual field that will be calculated later.
+ */
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;
+ Field *field= keyinfo->key_part[j].field;
+ if (!bitmap_is_set(table->write_set, field->field_index))
+ {
+ /* Check auto_increment */
+ if (field == table->next_number_field)
+ goto exit;
+ if (field->is_real_null() && !field->default_value)
+ goto exit;
+ }
}
- unique_keys++;
+ if (unique_keys++)
+ break;
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();
+ if (bf == BINLOG_FORMAT_STMT && !lex->is_stmt_unsafe())
+ {
+ 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;
+ DBUG_VOID_RETURN;
}
/*
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 0d1e14b1679..19466b3de90 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2016, Oracle and/or its affiliates.
- Copyright (c) 2009, 2021, MariaDB Corporation.
+ Copyright (c) 2009, 2022, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1054,7 +1054,7 @@ public:
/* We build without RTTI, so dynamic_cast can't be used. */
enum Type
{
- STATEMENT, PREPARED_STATEMENT, STORED_PROCEDURE, TABLE_ARENA
+ STATEMENT, PREPARED_STATEMENT, STORED_PROCEDURE
};
Query_arena(MEM_ROOT *mem_root_arg, enum enum_state state_arg) :
@@ -2169,6 +2169,39 @@ struct wait_for_commit
void reinit();
};
+
+class Sp_caches
+{
+public:
+ sp_cache *sp_proc_cache;
+ sp_cache *sp_func_cache;
+ sp_cache *sp_package_spec_cache;
+ sp_cache *sp_package_body_cache;
+ Sp_caches()
+ :sp_proc_cache(NULL),
+ sp_func_cache(NULL),
+ sp_package_spec_cache(NULL),
+ sp_package_body_cache(NULL)
+ { }
+ ~Sp_caches()
+ {
+ // All caches must be freed by the caller explicitly
+ DBUG_ASSERT(sp_proc_cache == NULL);
+ DBUG_ASSERT(sp_func_cache == NULL);
+ DBUG_ASSERT(sp_package_spec_cache == NULL);
+ DBUG_ASSERT(sp_package_body_cache == NULL);
+ }
+ void sp_caches_swap(Sp_caches &rhs)
+ {
+ swap_variables(sp_cache*, sp_proc_cache, rhs.sp_proc_cache);
+ swap_variables(sp_cache*, sp_func_cache, rhs.sp_func_cache);
+ swap_variables(sp_cache*, sp_package_spec_cache, rhs.sp_package_spec_cache);
+ swap_variables(sp_cache*, sp_package_body_cache, rhs.sp_package_body_cache);
+ }
+ void sp_caches_clear();
+};
+
+
extern "C" void my_message_sql(uint error, const char *str, myf MyFlags);
@@ -2189,7 +2222,8 @@ class THD: public THD_count, /* this must be first */
*/
public Item_change_list,
public MDL_context_owner,
- public Open_tables_state
+ public Open_tables_state,
+ public Sp_caches
{
private:
inline bool is_stmt_prepare() const
@@ -3183,10 +3217,6 @@ public:
enum_sql_command last_sql_command; // Last sql_command exceuted in mysql_execute_command()
sp_rcontext *spcont; // SP runtime context
- sp_cache *sp_proc_cache;
- sp_cache *sp_func_cache;
- sp_cache *sp_package_spec_cache;
- sp_cache *sp_package_body_cache;
/** number of name_const() substitutions, see sp_head.cc:subst_spvars() */
uint query_name_consts;
@@ -3969,8 +3999,7 @@ public:
bool is_item_tree_change_register_required()
{
- return !stmt_arena->is_conventional()
- || stmt_arena->type() == Query_arena::TABLE_ARENA;
+ return !stmt_arena->is_conventional();
}
void change_item_tree(Item **place, Item *new_value)
@@ -4588,18 +4617,18 @@ public:
mdl_context.release_transactional_locks(this);
}
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
+ 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.
- @returns 0 if no format is changed
- 1 if there is change in binlog format
+ One example would be binlog format for insert on duplicate key
+ (IODKU) but column with unique key is not inserted. We do not have
+ inserted columns info when we call decide_logging_format so on
+ later stage we call reconsider_logging_format_for_iodup()
*/
- int decide_logging_format_low(TABLE *table);
+ void reconsider_logging_format_for_iodup(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_expression_cache.cc b/sql/sql_expression_cache.cc
index 351ec258ddb..bc44ecd79fa 100644
--- a/sql/sql_expression_cache.cc
+++ b/sql/sql_expression_cache.cc
@@ -63,7 +63,7 @@ void Expression_cache_tmptable::disable_cache()
cache_table= NULL;
update_tracker();
if (tracker)
- tracker->cache= NULL;
+ tracker->detach_from_cache();
}
@@ -189,6 +189,8 @@ Expression_cache_tmptable::~Expression_cache_tmptable()
else
{
update_tracker();
+ if (tracker)
+ tracker->detach_from_cache();
tracker= NULL;
}
}
diff --git a/sql/sql_expression_cache.h b/sql/sql_expression_cache.h
index 61e0c4c69b3..d4bb252dccb 100644
--- a/sql/sql_expression_cache.h
+++ b/sql/sql_expression_cache.h
@@ -83,7 +83,11 @@ public:
cache(c), hit(0), miss(0), state(UNINITED)
{}
+private:
+ // This can be NULL if the cache is already deleted
Expression_cache *cache;
+
+public:
ulong hit, miss;
enum expr_cache_state state;
@@ -91,6 +95,7 @@ public:
void set(ulong h, ulong m, enum expr_cache_state s)
{hit= h; miss= m; state= s;}
+ void detach_from_cache() { cache= NULL; }
void fetch_current_stats()
{
if (cache)
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index 073d523b876..eb0dc1c2b3f 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -699,8 +699,10 @@ mysql_ha_fix_cond_and_key(SQL_HANDLER *handler,
if (!in_prepare)
{
MY_BITMAP *old_map= dbug_tmp_use_all_columns(table, &table->write_set);
- (void) item->save_in_field(key_part->field, 1);
+ int res= item->save_in_field(key_part->field, 1);
dbug_tmp_restore_column_map(&table->write_set, old_map);
+ if (res)
+ return 1;
}
key_len+= key_part->store_length;
keypart_map= (keypart_map << 1) | 1;
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 460fbba4ac5..7e848b3906e 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2016, Oracle and/or its affiliates.
- Copyright (c) 2010, 2021, MariaDB Corporation
+ Copyright (c) 2010, 2022, MariaDB Corporation
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -951,6 +951,12 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
}
THD_STAGE_INFO(thd, stage_update);
+
+ if (duplic == DUP_UPDATE)
+ {
+ restore_record(table,s->default_values); // Get empty record
+ thd->reconsider_logging_format_for_iodup(table);
+ }
do
{
DBUG_PRINT("info", ("iteration %llu", iteration));
@@ -1063,7 +1069,6 @@ 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_lex.cc b/sql/sql_lex.cc
index e622d5fb863..290dcdb33b9 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2019, Oracle and/or its affiliates.
- Copyright (c) 2009, 2021, MariaDB Corporation.
+ Copyright (c) 2009, 2022, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -209,7 +209,6 @@ init_lex_with_single_table(THD *thd, TABLE *table, LEX *lex)
return TRUE;
context->resolve_in_table_list_only(table_list);
lex->use_only_table_context= TRUE;
- lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_VCOL_EXPR;
select_lex->cur_pos_in_select_list= UNDEF_POS;
table->map= 1; //To ensure correct calculation of const item
table_list->table= table;
@@ -4608,17 +4607,21 @@ void SELECT_LEX::update_used_tables()
while ((tl= ti++))
{
TABLE_LIST *embedding= tl;
- do
+ if (!is_eliminated_table(join->eliminated_tables, tl))
{
- bool maybe_null;
- if ((maybe_null= MY_TEST(embedding->outer_join)))
+ do
{
- tl->table->maybe_null= maybe_null;
- break;
+ bool maybe_null;
+ if ((maybe_null= MY_TEST(embedding->outer_join)))
+ {
+ tl->table->maybe_null= maybe_null;
+ break;
+ }
}
+ while ((embedding= embedding->embedding));
}
- while ((embedding= embedding->embedding));
- if (tl->on_expr)
+
+ if (tl->on_expr && !is_eliminated_table(join->eliminated_tables, tl))
{
tl->on_expr->update_used_tables();
tl->on_expr->walk(&Item::eval_not_null_tables, 0, NULL);
@@ -4642,8 +4645,11 @@ void SELECT_LEX::update_used_tables()
if (embedding->on_expr &&
embedding->nested_join->join_list.head() == tl)
{
- embedding->on_expr->update_used_tables();
- embedding->on_expr->walk(&Item::eval_not_null_tables, 0, NULL);
+ if (!is_eliminated_table(join->eliminated_tables, embedding))
+ {
+ embedding->on_expr->update_used_tables();
+ embedding->on_expr->walk(&Item::eval_not_null_tables, 0, NULL);
+ }
}
tl= embedding;
embedding= tl->embedding;
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 6a3a01f69d6..3db50222a27 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -4436,6 +4436,29 @@ public:
return create_info.vers_info;
}
+ /* The list of history-generating DML commands */
+ bool vers_history_generating() const
+ {
+ switch (sql_command)
+ {
+ case SQLCOM_DELETE:
+ return !vers_conditions.delete_history;
+ case SQLCOM_UPDATE:
+ case SQLCOM_UPDATE_MULTI:
+ case SQLCOM_DELETE_MULTI:
+ case SQLCOM_REPLACE:
+ case SQLCOM_REPLACE_SELECT:
+ return true;
+ case SQLCOM_INSERT:
+ case SQLCOM_INSERT_SELECT:
+ return duplicates == DUP_UPDATE;
+ case SQLCOM_LOAD:
+ return duplicates == DUP_REPLACE;
+ default:
+ return false;
+ }
+ }
+
int add_period(Lex_ident name, Lex_ident_sys_st start, Lex_ident_sys_st end)
{
if (lex_string_cmp(system_charset_info, &start, &end) == 0)
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 6a1b849b912..b5e6b6540c5 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -8852,6 +8852,7 @@ bool st_select_lex::add_window_def(THD *thd,
fields_in_window_functions+= win_part_list_ptr->elements +
win_order_list_ptr->elements;
}
+ win_def->win_spec_number= window_specs.elements;
return (win_def == NULL || window_specs.push_back(win_def));
}
@@ -8879,6 +8880,7 @@ bool st_select_lex::add_window_spec(THD *thd,
win_order_list_ptr->elements;
}
thd->lex->win_spec= win_spec;
+ win_spec->win_spec_number= window_specs.elements;
return (win_spec == NULL || window_specs.push_back(win_spec));
}
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index 87b4d241028..2790f69e41e 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -355,7 +355,8 @@ bool check_valid_path(const char *path, size_t len)
static void fix_dl_name(MEM_ROOT *root, LEX_CSTRING *dl)
{
const size_t so_ext_len= sizeof(SO_EXT) - 1;
- if (my_strcasecmp(&my_charset_latin1, dl->str + dl->length - so_ext_len,
+ if (dl->length < so_ext_len ||
+ my_strcasecmp(&my_charset_latin1, dl->str + dl->length - so_ext_len,
SO_EXT))
{
char *s= (char*)alloc_root(root, dl->length + so_ext_len + 1);
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 735e00dd091..1b8147a6cfb 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -18087,7 +18087,7 @@ Field *Item_default_value::create_tmp_field_ex(TABLE *table,
Tmp_field_src *src,
const Tmp_field_param *param)
{
- if (field->default_value && (field->flags & BLOB_FLAG))
+ if (field->default_value || (field->flags & BLOB_FLAG))
{
/*
We have to use a copy function when using a blob with default value
@@ -18488,6 +18488,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
table->copy_blobs= 1;
table->in_use= thd;
table->no_rows_with_nulls= param->force_not_null_cols;
+ table->expr_arena= thd;
table->update_handler= NULL;
table->check_unique_buf= NULL;
@@ -25483,15 +25484,17 @@ change_to_use_tmp_fields(THD *thd, Ref_ptr_array ref_pointer_array,
for (uint i= 0; (item= it++); i++)
{
Field *field;
- if ((item->with_sum_func() && item->type() != Item::SUM_FUNC_ITEM) ||
+ enum Item::Type item_type= item->type();
+ if ((item->with_sum_func() && item_type != Item::SUM_FUNC_ITEM) ||
item->with_window_func)
item_field= item;
- else if (item->type() == Item::FIELD_ITEM)
+ else if (item_type == Item::FIELD_ITEM ||
+ item_type == Item::DEFAULT_VALUE_ITEM)
{
if (!(item_field= item->get_tmp_table_item(thd)))
DBUG_RETURN(true);
}
- else if (item->type() == Item::FUNC_ITEM &&
+ else if (item_type == Item::FUNC_ITEM &&
((Item_func*)item)->functype() == Item_func::SUSERVAR_FUNC)
{
field= item->get_tmp_table_field();
@@ -27369,7 +27372,7 @@ static void print_table_array(THD *thd,
too)
*/
-static bool is_eliminated_table(table_map eliminated_tables, TABLE_LIST *tbl)
+bool is_eliminated_table(table_map eliminated_tables, TABLE_LIST *tbl)
{
return eliminated_tables &&
((tbl->table && (tbl->table->map & eliminated_tables)) ||
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 28bf33997a0..9a6237f00a6 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -2,7 +2,7 @@
#define SQL_SELECT_INCLUDED
/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
- Copyright (c) 2008, 2020, MariaDB Corporation.
+ Copyright (c) 2008, 2022, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -2540,6 +2540,8 @@ int create_sort_index(THD *thd, JOIN *join, JOIN_TAB *tab, Filesort *fsort);
JOIN_TAB *first_explain_order_tab(JOIN* join);
JOIN_TAB *next_explain_order_tab(JOIN* join, JOIN_TAB* tab);
+bool is_eliminated_table(table_map eliminated_tables, TABLE_LIST *tbl);
+
bool check_simple_equality(THD *thd, const Item::Context &ctx,
Item *left_item, Item *right_item,
COND_EQUAL *cond_equal);
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index d9d5c5d135c..eb3ee3d5f74 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -5181,6 +5181,7 @@ public:
int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
{
+ DBUG_ENTER("get_all_tables");
LEX *lex= thd->lex;
TABLE *table= tables->table;
TABLE_LIST table_acl_check;
@@ -5198,7 +5199,29 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
uint table_open_method= tables->table_open_method;
bool can_deadlock;
MEM_ROOT tmp_mem_root;
- DBUG_ENTER("get_all_tables");
+ /*
+ We're going to open FRM files for tables.
+ In case of VIEWs that contain stored function calls,
+ these stored functions will be parsed and put to the SP cache.
+
+ Suppose we have a view containing a stored function call:
+ CREATE VIEW v1 AS SELECT f1() AS c1;
+ and now we're running:
+ SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME=f1();
+ If a parallel thread invalidates the cache,
+ e.g. by creating or dropping some stored routine,
+ the SELECT query will re-parse f1() when processing "v1"
+ and replace the outdated cached version of f1() to a new one.
+ But the old version of f1() is referenced from the m_sp member
+ of the Item_func_sp instances used in the WHERE condition.
+ We cannot destroy it. To avoid such clashes, let's remember
+ all old routines into a temporary SP cache collection
+ and process tables with a new empty temporary SP cache collection.
+ Then restore to the old SP cache collection at the end.
+ */
+ Sp_caches old_sp_caches;
+
+ old_sp_caches.sp_caches_swap(*thd);
bzero(&tmp_mem_root, sizeof(tmp_mem_root));
@@ -5374,6 +5397,13 @@ err:
thd->restore_backup_open_tables_state(&open_tables_state_backup);
free_root(&tmp_mem_root, 0);
+ /*
+ Now restore to the saved SP cache collection
+ and clear the temporary SP cache collection.
+ */
+ old_sp_caches.sp_caches_swap(*thd);
+ old_sp_caches.sp_caches_clear();
+
DBUG_RETURN(error);
}
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index d58dbc2b0d6..9414735fa4e 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -8100,6 +8100,8 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
{
/* New column definitions are added here */
List<Create_field> new_create_list;
+ /* System-invisible fields must be added last */
+ List<Create_field> new_create_tail;
/* New key definitions are added here */
List<Key> new_key_list;
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
@@ -8325,7 +8327,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
dropped_sys_vers_fields|= field->flags;
drop_it.remove();
}
- else
+ else if (field->invisible < INVISIBLE_SYSTEM)
{
/*
This field was not dropped and not changed, add it to the list
@@ -8350,6 +8352,12 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
alter_it.remove();
}
}
+ else
+ {
+ DBUG_ASSERT(field->invisible == INVISIBLE_SYSTEM);
+ def= new (thd->mem_root) Create_field(thd, field, field);
+ new_create_tail.push_back(def, thd->mem_root);
+ }
}
dropped_sys_vers_fields &= VERS_SYSTEM_FIELD;
if ((dropped_sys_vers_fields ||
@@ -8482,6 +8490,9 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
alter_it.remove();
}
}
+
+ new_create_list.append(&new_create_tail);
+
if (unlikely(alter_info->alter_list.elements))
{
my_error(ER_BAD_FIELD_ERROR, MYF(0),
diff --git a/sql/sql_type.cc b/sql/sql_type.cc
index e0a6169df3d..28fd2418e3b 100644
--- a/sql/sql_type.cc
+++ b/sql/sql_type.cc
@@ -2057,7 +2057,6 @@ Type_handler_decimal_result::make_num_distinct_aggregator_field(
const Item *item)
const
{
- DBUG_ASSERT(item->decimals <= DECIMAL_MAX_SCALE);
return new (mem_root)
Field_new_decimal(NULL, item->max_length,
(uchar *) (item->maybe_null ? "" : 0),
diff --git a/sql/sql_window.cc b/sql/sql_window.cc
index 876ddef8f65..bf36b592d96 100644
--- a/sql/sql_window.cc
+++ b/sql/sql_window.cc
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2016, 2017 MariaDB
+ Copyright (c) 2016, 2022 MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -424,16 +424,49 @@ ORDER *st_select_lex::find_common_window_func_partition_fields(THD *thd)
#define CMP_GT 2 // Greater then
static
-int compare_order_elements(ORDER *ord1, ORDER *ord2)
+int compare_order_elements(ORDER *ord1, int weight1,
+ ORDER *ord2, int weight2)
{
if (*ord1->item == *ord2->item && ord1->direction == ord2->direction)
return CMP_EQ;
Item *item1= (*ord1->item)->real_item();
Item *item2= (*ord2->item)->real_item();
- DBUG_ASSERT(item1->type() == Item::FIELD_ITEM &&
- item2->type() == Item::FIELD_ITEM);
- int cmp= ((Item_field *) item1)->field->field_index -
- ((Item_field *) item2)->field->field_index;
+
+ bool item1_field= (item1->type() == Item::FIELD_ITEM);
+ bool item2_field= (item2->type() == Item::FIELD_ITEM);
+
+ ptrdiff_t cmp;
+ if (item1_field && item2_field)
+ {
+ DBUG_ASSERT(((Item_field *) item1)->field->table ==
+ ((Item_field *) item2)->field->table);
+ cmp= ((Item_field *) item1)->field->field_index -
+ ((Item_field *) item2)->field->field_index;
+ }
+ else if (item1_field && !item2_field)
+ return CMP_LT;
+ else if (!item1_field && item2_field)
+ return CMP_LT;
+ else
+ {
+ /*
+ Ok, item1_field==NULL and item2_field==NULL.
+ We're not able to compare Item expressions. Order them according to
+ their passed "weight" (which comes from Window_spec::win_spec_number):
+ */
+ if (weight1 != weight2)
+ cmp= weight1 - weight2;
+ else
+ {
+ /*
+ The weight is the same. That is, the elements come from the same
+ window specification... This shouldn't happen.
+ */
+ DBUG_ASSERT(0);
+ cmp= item1 - item2;
+ }
+ }
+
if (cmp == 0)
{
if (ord1->direction == ord2->direction)
@@ -446,7 +479,9 @@ int compare_order_elements(ORDER *ord1, ORDER *ord2)
static
int compare_order_lists(SQL_I_List<ORDER> *part_list1,
- SQL_I_List<ORDER> *part_list2)
+ int spec_number1,
+ SQL_I_List<ORDER> *part_list2,
+ int spec_number2)
{
if (part_list1 == part_list2)
return CMP_EQ;
@@ -471,7 +506,8 @@ int compare_order_lists(SQL_I_List<ORDER> *part_list1,
if (!elem1 || !elem2)
break;
- if ((cmp= compare_order_elements(elem1, elem2)))
+ if ((cmp= compare_order_elements(elem1, spec_number1,
+ elem2, spec_number2)))
return cmp;
}
if (elem1)
@@ -566,7 +602,9 @@ int compare_window_spec_joined_lists(Window_spec *win_spec1,
win_spec1->join_partition_and_order_lists();
win_spec2->join_partition_and_order_lists();
int cmp= compare_order_lists(win_spec1->partition_list,
- win_spec2->partition_list);
+ win_spec1->win_spec_number,
+ win_spec2->partition_list,
+ win_spec2->win_spec_number);
win_spec1->disjoin_partition_and_order_lists();
win_spec2->disjoin_partition_and_order_lists();
return cmp;
@@ -584,7 +622,9 @@ int compare_window_funcs_by_window_specs(Item_window_func *win_func1,
if (win_spec1 == win_spec2)
return CMP_EQ;
cmp= compare_order_lists(win_spec1->partition_list,
- win_spec2->partition_list);
+ win_spec1->win_spec_number,
+ win_spec2->partition_list,
+ win_spec2->win_spec_number);
if (cmp == CMP_EQ)
{
/*
@@ -603,7 +643,9 @@ int compare_window_funcs_by_window_specs(Item_window_func *win_func1,
}
cmp= compare_order_lists(win_spec1->order_list,
- win_spec2->order_list);
+ win_spec1->win_spec_number,
+ win_spec2->order_list,
+ win_spec2->win_spec_number);
if (cmp != CMP_EQ)
return cmp;
@@ -700,7 +742,9 @@ void order_window_funcs_by_window_specs(List<Item_window_func> *win_func_list)
int cmp;
if (win_spec_prev->partition_list == win_spec_curr->partition_list)
cmp= compare_order_lists(win_spec_prev->order_list,
- win_spec_curr->order_list);
+ win_spec_prev->win_spec_number,
+ win_spec_curr->order_list,
+ win_spec_curr->win_spec_number);
else
cmp= compare_window_spec_joined_lists(win_spec_prev, win_spec_curr);
if (!(CMP_LT_C <= cmp && cmp <= CMP_GT_C))
diff --git a/sql/sql_window.h b/sql/sql_window.h
index 5e76a33dcd0..66ea8c7dd4d 100644
--- a/sql/sql_window.h
+++ b/sql/sql_window.h
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2016, 2017 MariaDB
+ Copyright (c) 2016, 2022 MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -120,10 +120,15 @@ class Window_spec : public Sql_alloc
Window_spec *referenced_win_spec;
- Window_spec(LEX_CSTRING *win_ref,
- SQL_I_List<ORDER> *part_list,
- SQL_I_List<ORDER> *ord_list,
- Window_frame *win_frame)
+ /*
+ Window_spec objects are numbered by the number of their appearance in the
+ query. This is used by compare_order_elements() to provide a predictable
+ ordering of PARTITION/ORDER BY clauses.
+ */
+ int win_spec_number;
+
+ Window_spec(LEX_CSTRING *win_ref, SQL_I_List<ORDER> *part_list,
+ SQL_I_List<ORDER> *ord_list, Window_frame *win_frame)
: window_names_are_checked(false), window_ref(win_ref),
partition_list(part_list), save_partition_list(NULL),
order_list(ord_list), save_order_list(NULL),
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index cb0d8fff50a..e2e554f6d82 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2015, Oracle and/or its affiliates.
- Copyright (c) 2010, 2021, MariaDB
+ Copyright (c) 2010, 2022, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -834,7 +834,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
/*
We should not introduce any further shift/reduce conflicts.
*/
-%expect 68
+%expect 72
/*
Comments for TOKENS.
@@ -947,6 +947,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%token FIRST_VALUE_SYM /* SQL-2011 */
%token FLOAT_NUM
%token FLOAT_SYM /* SQL-2003-R */
+%token FORCE_LOOKAHEAD /* INTERNAL never returned by the lexer */
%token FOREIGN /* SQL-2003-R */
%token FOR_SYM /* SQL-2003-R */
%token FOR_SYSTEM_TIME_SYM /* INTERNAL */
@@ -3057,6 +3058,9 @@ sequence_def:
}
;
+/* this rule is used to force look-ahead in the parser */
+force_lookahead: {} | FORCE_LOOKAHEAD {} ;
+
server_def:
SERVER_SYM opt_if_not_exists ident_or_text
{
@@ -3258,7 +3262,7 @@ ev_sql_stmt:
lex->sphead->set_body_start(thd, lip->get_cpp_ptr());
}
- sp_proc_stmt
+ sp_proc_stmt force_lookahead
{
/* return back to the original memory root ASAP */
if (Lex->sp_body_finalize_event(thd))
@@ -18062,8 +18066,8 @@ trigger_tail:
lex->sphead->set_body_start(thd, lip->get_cpp_tok_start());
}
- sp_proc_stmt /* $19 */
- { /* $20 */
+ sp_proc_stmt /* $19 */ force_lookahead /* $20 */
+ { /* $21 */
LEX *lex= Lex;
lex->sql_command= SQLCOM_CREATE_TRIGGER;
@@ -18113,7 +18117,7 @@ sf_c_chistics_and_body:
lex->sphead->set_c_chistics(lex->sp_chistics);
lex->sphead->set_body_start(thd, YYLIP->get_cpp_tok_start());
}
- sp_proc_stmt_in_returns_clause
+ sp_proc_stmt_in_returns_clause force_lookahead
{
if (unlikely(Lex->sp_body_finalize_function(thd)))
MYSQL_YYABORT;
@@ -18135,7 +18139,7 @@ sp_tail:
Lex->sphead->set_c_chistics(Lex->sp_chistics);
Lex->sphead->set_body_start(thd, YYLIP->get_cpp_tok_start());
}
- sp_proc_stmt
+ sp_proc_stmt force_lookahead
{
if (unlikely(Lex->sp_body_finalize_procedure(thd)))
MYSQL_YYABORT;
diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy
index 2b22d585a94..c079598a169 100644
--- a/sql/sql_yacc_ora.yy
+++ b/sql/sql_yacc_ora.yy
@@ -310,7 +310,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
/*
We should not introduce any further shift/reduce conflicts.
*/
-%expect 70
+%expect 73
/*
Comments for TOKENS.
@@ -423,6 +423,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%token FIRST_VALUE_SYM /* SQL-2011 */
%token FLOAT_NUM
%token FLOAT_SYM /* SQL-2003-R */
+%token FORCE_LOOKAHEAD /* INTERNAL never returned by the lexer */
%token FOREIGN /* SQL-2003-R */
%token FOR_SYM /* SQL-2003-R */
%token FOR_SYSTEM_TIME_SYM /* INTERNAL */
@@ -2832,6 +2833,9 @@ sequence_def:
}
;
+/* this rule is used to force look-ahead in the parser */
+force_lookahead: {} | FORCE_LOOKAHEAD {} ;
+
server_def:
SERVER_SYM opt_if_not_exists ident_or_text
{
@@ -3033,7 +3037,7 @@ ev_sql_stmt:
lex->sphead->set_body_start(thd, lip->get_cpp_ptr());
}
- sp_proc_stmt
+ sp_proc_stmt force_lookahead
{
/* return back to the original memory root ASAP */
if (Lex->sp_body_finalize_event(thd))
@@ -18286,8 +18290,8 @@ trigger_tail:
lex->sphead->set_body_start(thd, lip->get_cpp_tok_start());
}
- sp_proc_stmt /* $19 */
- { /* $20 */
+ sp_proc_stmt /* $19 */ force_lookahead /* $20 */
+ { /* $21 */
LEX *lex= Lex;
lex->sql_command= SQLCOM_CREATE_TRIGGER;
@@ -18336,7 +18340,7 @@ sf_c_chistics_and_body_standalone:
lex->sphead->set_body_start(thd, YYLIP->get_cpp_tok_start());
}
sp_tail_is
- sp_body
+ sp_body force_lookahead
{
if (unlikely(Lex->sp_body_finalize_function(thd)))
MYSQL_YYABORT;
diff --git a/sql/table.cc b/sql/table.cc
index 6aa2dc872ad..00b498fdd77 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -50,17 +50,6 @@
#define MYSQL57_GENERATED_FIELD 128
#define MYSQL57_GCOL_HEADER_SIZE 4
-class Table_arena: public Query_arena
-{
-public:
- Table_arena(MEM_ROOT *mem_root, enum enum_state state_arg) :
- Query_arena(mem_root, state_arg){}
- virtual Type type() const
- {
- return TABLE_ARENA;
- }
-};
-
struct extra2_fields
{
LEX_CUSTRING version;
@@ -1139,8 +1128,8 @@ bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table,
We need to use CONVENTIONAL_EXECUTION here to ensure that
any new items created by fix_fields() are not reverted.
*/
- table->expr_arena= new (alloc_root(mem_root, sizeof(Table_arena)))
- Table_arena(mem_root,
+ table->expr_arena= new (alloc_root(mem_root, sizeof(Query_arena)))
+ Query_arena(mem_root,
Query_arena::STMT_CONVENTIONAL_EXECUTION);
if (!table->expr_arena)
DBUG_RETURN(1);
@@ -3352,8 +3341,7 @@ class Vcol_expr_context
bool inited;
THD *thd;
TABLE *table;
- LEX *old_lex;
- LEX lex;
+ Query_arena backup_arena;
table_map old_map;
Security_context *save_security_ctx;
sql_mode_t save_sql_mode;
@@ -3363,7 +3351,6 @@ public:
inited(false),
thd(_thd),
table(_table),
- old_lex(thd->lex),
old_map(table->map),
save_security_ctx(thd->security_ctx),
save_sql_mode(thd->variables.sql_mode) {}
@@ -3375,18 +3362,6 @@ public:
bool Vcol_expr_context::init()
{
- /*
- As this is vcol expression we must narrow down name resolution to
- single table.
- */
- if (init_lex_with_single_table(thd, table, &lex))
- {
- my_error(ER_OUT_OF_RESOURCES, MYF(0));
- table->map= old_map;
- return true;
- }
-
- lex.sql_command= old_lex->sql_command;
thd->variables.sql_mode= 0;
TABLE_LIST const *tl= table->pos_in_table_list;
@@ -3395,6 +3370,8 @@ bool Vcol_expr_context::init()
if (table->pos_in_table_list->security_ctx)
thd->security_ctx= tl->security_ctx;
+ thd->set_n_backup_active_arena(table->expr_arena, &backup_arena);
+
inited= true;
return false;
}
@@ -3403,9 +3380,9 @@ Vcol_expr_context::~Vcol_expr_context()
{
if (!inited)
return;
- end_lex_with_single_table(thd, table, old_lex);
table->map= old_map;
thd->security_ctx= save_security_ctx;
+ thd->restore_active_arena(table->expr_arena, &backup_arena);
thd->variables.sql_mode= save_sql_mode;
}
@@ -3756,6 +3733,7 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share,
outparam->s= share;
outparam->db_stat= db_stat;
outparam->write_row_record= NULL;
+ outparam->status= STATUS_NO_RECORD;
if (share->incompatible_version &&
!(ha_open_flags & (HA_OPEN_FOR_ALTER | HA_OPEN_FOR_REPAIR)))
@@ -6642,7 +6620,7 @@ Item *Field_iterator_view::create_item(THD *thd)
Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref,
LEX_CSTRING *name)
{
- bool save_wrapper= thd->lex->first_select_lex()->no_wrap_view_item;
+ bool save_wrapper= thd->lex->current_select->no_wrap_view_item;
Item *field= *field_ref;
DBUG_ENTER("create_view_field");
diff --git a/sql/tztime.cc b/sql/tztime.cc
index 80035a5b906..7319084c28b 100644
--- a/sql/tztime.cc
+++ b/sql/tztime.cc
@@ -2747,9 +2747,9 @@ main(int argc, char **argv)
sql_log_bin and wsrep_on to avoid Galera replicating below
TRUNCATE TABLE clauses. This will allow user to set different
time zones to nodes in Galera cluster. */
- printf("set @prep1=if((select count(*) from information_schema.global_variables where variable_name='wsrep_on' and variable_value='ON'), 'SET SESSION SQL_LOG_BIN=?, WSREP_ON=OFF;', 'do ?');\n"
- "prepare set_wsrep_write_binlog from @prep1;\n"
- "set @toggle=0; execute set_wsrep_write_binlog using @toggle;\n"
+ printf("set @prep1=if((select count(*) from information_schema.global_variables where variable_name='wsrep_on' and variable_value='ON'), 'SET SESSION WSREP_ON=OFF', 'do 0');\n"
+ "SET SESSION SQL_LOG_BIN=0;\n"
+ "execute immediate @prep1;\n"
"%s%s", trunc_tables, lock_tables);
else
// Alter time zone tables to InnoDB if wsrep_on is enabled