Commit 70afc627 authored by Oleksandr Byelkin's avatar Oleksandr Byelkin

Merge branch '10.6' into 10.11

parents 62bfcfd8 fc5772ce
......@@ -2000,7 +2000,7 @@ struct my_option xb_server_options[] =
0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0 },
{"check-privileges", OPT_XTRA_CHECK_PRIVILEGES, "Check database user "
"privileges fro the backup user",
"privileges for the backup user",
&opt_check_privileges, &opt_check_privileges,
0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0 },
......
if (`select version() like '%valgrind%' || version() like '%asan%'`)
{
skip Does not run with binaries built with valgrind or asan;
}
......@@ -27,4 +27,20 @@ a
DROP TABLE t1;
DROP VIEW v1, v2;
#
# MDEV-34771: Types mismatch when cloning items causes debug assertion
#
CREATE VIEW t AS SELECT 1 AS a;
SELECT * FROM t WHERE a=b'';
a
drop view t;
#
# MDEV-34776: Assertion failure in Item_string::do_build_clone
#
CREATE VIEW v AS SELECT version() AS f;
SELECT * FROM v WHERE f = '10.5.20';
f
drop view v;
#
# End of 10.5 tests
#
......@@ -30,4 +30,22 @@ SELECT * FROM v2 WHERE a='' AND CASE '' WHEN '' THEN '' ELSE a END='';
DROP TABLE t1;
DROP VIEW v1, v2;
--echo #
--echo # MDEV-34771: Types mismatch when cloning items causes debug assertion
--echo #
CREATE VIEW t AS SELECT 1 AS a;
SELECT * FROM t WHERE a=b'';
drop view t;
--echo #
--echo # MDEV-34776: Assertion failure in Item_string::do_build_clone
--echo #
CREATE VIEW v AS SELECT version() AS f;
SELECT * FROM v WHERE f = '10.5.20';
drop view v;
--echo #
--echo # End of 10.5 tests
--echo #
--source include/not_msan.inc
--source include/not_valgrind.inc
--source include/not_valgrind_build.inc
--echo # MDEV-20699 do not cache SP in SHOW CREATE
--echo # Warmup round, this might allocate some memory for session variable
......
......@@ -5942,7 +5942,9 @@ WHERE SLEEP(0.1) OR c < 'p' OR b = ( SELECT MIN(b) FROM t2 );
--enable_ps2_protocol
--echo # The following shows that t2 was indeed scanned with a full scan.
--sorted_result
show table_statistics;
--sorted_result
show index_statistics;
set global userstat=@tmp_mdev410;
......
......@@ -4925,6 +4925,9 @@ class Item_string_sys :public Item_string
Item_string_sys(THD *thd, const char *str):
Item_string(thd, str, (uint) strlen(str), system_charset_info)
{ }
Item *do_get_copy(THD *thd) const override
{ return get_item_copy<Item_string_sys>(thd, this); }
Item *do_build_clone(THD *thd) const override { return get_copy(thd); }
};
......@@ -4939,6 +4942,9 @@ class Item_string_ascii :public Item_string
Item_string(thd, str, (uint) strlen(str), &my_charset_latin1,
DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII)
{ }
Item *do_get_copy(THD *thd) const override
{ return get_item_copy<Item_string_ascii>(thd, this); }
Item *do_build_clone(THD *thd) const override { return get_copy(thd); }
};
......@@ -4975,6 +4981,9 @@ class Item_static_string_func :public Item_string
// require fix_fields() to be re-run for every statement.
return mark_unsupported_function(func_name.str, arg, VCOL_TIME_FUNC);
}
Item *do_get_copy(THD *thd) const override
{ return get_item_copy<Item_static_string_func>(thd, this); }
Item *do_build_clone(THD *thd) const override { return get_copy(thd); }
};
......@@ -4992,6 +5001,9 @@ class Item_partition_func_safe_string: public Item_string
{
return mark_unsupported_function("safe_string", arg, VCOL_IMPOSSIBLE);
}
Item *do_get_copy(THD *thd) const override
{ return get_item_copy<Item_partition_func_safe_string>(thd, this); }
Item *do_build_clone(THD *thd) const override { return get_copy(thd); }
};
......@@ -5153,6 +5165,9 @@ class Item_bin_string: public Item_hex_hybrid
public:
Item_bin_string(THD *thd, const char *str, size_t str_length);
void print(String *str, enum_query_type query_type) override;
Item *do_get_copy(THD *thd) const override
{ return get_item_copy<Item_bin_string>(thd, this); }
Item *do_build_clone(THD *thd) const override { return get_copy(thd); }
};
......
......@@ -9206,10 +9206,22 @@ fill_record_n_invoke_before_triggers(THD *thd, TABLE *table,
if (!result && triggers)
{
void *save_bulk_param= thd->bulk_param;
/*
Reset the sentinel thd->bulk_param in order not to consume the next
values of a bound array in case one of statement executed by
the trigger's body is INSERT statement.
*/
thd->bulk_param= nullptr;
if (triggers->process_triggers(thd, event, TRG_ACTION_BEFORE,
TRUE) ||
not_null_fields_have_null_values(table))
{
thd->bulk_param= save_bulk_param;
return TRUE;
}
thd->bulk_param= save_bulk_param;
/*
Re-calculate virtual fields to cater for cases when base columns are
......
......@@ -830,13 +830,17 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
delete_history);
if (delete_record)
{
void *save_bulk_param= thd->bulk_param;
thd->bulk_param= nullptr;
if (!delete_history && table->triggers &&
table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
TRG_ACTION_BEFORE, FALSE))
{
error= 1;
thd->bulk_param= save_bulk_param;
break;
}
thd->bulk_param= save_bulk_param;
// no LIMIT / OFFSET
if (returning && result->send_data(returning->item_list) < 0)
......@@ -867,13 +871,16 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
if (likely(!error))
{
deleted++;
thd->bulk_param= nullptr;
if (!delete_history && table->triggers &&
table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
TRG_ACTION_AFTER, FALSE))
{
error= 1;
thd->bulk_param= save_bulk_param;
break;
}
thd->bulk_param= save_bulk_param;
if (!--limit && using_limit)
{
error= -1;
......
......@@ -309,14 +309,27 @@ Diagnostics_area::reset_diagnostics_area()
m_message[0]= '\0';
Sql_state_errno::clear();
Sql_user_condition_identity::clear();
m_affected_rows= 0;
m_last_insert_id= 0;
m_statement_warn_count= 0;
if (!is_bulk_op())
{
m_affected_rows= 0;
m_statement_warn_count= 0;
}
#endif
get_warning_info()->clear_error_condition();
set_is_sent(false);
/** Tiny reset in debug mode to see garbage right away */
m_status= DA_EMPTY;
if (!is_bulk_op())
/*
For BULK DML operations (e.g. UPDATE) the data member m_status
has the value DA_OK_BULK. Keep this value in order to handle
m_affected_rows, m_statement_warn_count in correct way. Else,
the number of rows and the number of warnings affected by
the last statement executed as part of a trigger fired by the dml
(e.g. UPDATE statement fires a trigger on AFTER UPDATE) would counts
rows modified by trigger's statement.
*/
m_status= DA_EMPTY;
DBUG_VOID_RETURN;
}
......
......@@ -1078,6 +1078,11 @@ class Diagnostics_area: public Sql_state_errno,
return m_affected_rows;
}
void set_message(const char *msg)
{
strmake_buf(m_message, msg);
}
ulonglong last_insert_id() const
{
DBUG_ASSERT(m_status == DA_OK || m_status == DA_OK_BULK);
......
......@@ -1053,19 +1053,11 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list,
*/
restore_record(table,s->default_values); // Get empty record
table->reset_default_fields();
/*
Reset the sentinel thd->bulk_param in order not to consume the next
values of a bound array in case one of statement executed by
the trigger's body is INSERT statement.
*/
void *save_bulk_param= thd->bulk_param;
thd->bulk_param= nullptr;
if (unlikely(fill_record_n_invoke_before_triggers(thd, table, fields,
*values, 0,
TRG_EVENT_INSERT)))
{
thd->bulk_param= save_bulk_param;
if (values_list.elements != 1 && ! thd->is_error())
{
info.records++;
......@@ -1079,7 +1071,6 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list,
error=1;
break;
}
thd->bulk_param= save_bulk_param;
}
else
{
......@@ -1372,7 +1363,18 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list,
*/
if (returning)
result->send_eof();
else
else if (!(thd->in_sub_stmt & SUB_STMT_TRIGGER))
/*
Set the status and the number of affected rows in Diagnostics_area
only in case the INSERT statement is not processed as part of a trigger
invoked by some other DML statement. Else we would result in incorrect
number of affected rows for bulk DML operations, e.g. the UPDATE
statement (called via PS protocol). It would happen since the data
member Diagnostics_area::m_affected_rows modified twice per DML
statement - first time at the end of handling the INSERT statement
invoking by a trigger fired on handling the original DML statement,
and the second time at the end of handling the original DML statement.
*/
my_ok(thd, info.copied + info.deleted +
((thd->client_capabilities & CLIENT_FOUND_ROWS) ?
info.touched : info.updated), id);
......@@ -1394,7 +1396,18 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list,
(long) thd->get_stmt_da()->current_statement_warn_count());
if (returning)
result->send_eof();
else
else if (!(thd->in_sub_stmt & SUB_STMT_TRIGGER))
/*
Set the status and the number of affected rows in Diagnostics_area
only in case the INSERT statement is not processed as part of a trigger
invoked by some other DML statement. Else we would result in incorrect
number of affected rows for bulk DML operations, e.g. the UPDATE
statement (called via PS protocol). It would happen since the data
member Diagnostics_area::m_affected_rows modified twice per DML
statement - first time at the end of handling the INSERT statement
invoking by a trigger fired on handling the original DML statement,
and the second time at the end of handling the original DML statement.
*/
::my_ok(thd, info.copied + info.deleted + updated, id, buff);
}
thd->abort_on_warning= 0;
......
......@@ -1165,13 +1165,19 @@ int mysql_update(THD *thd,
rows_inserted++;
}
void *save_bulk_param= thd->bulk_param;
thd->bulk_param= nullptr;
if (table->triggers &&
unlikely(table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
TRG_ACTION_AFTER, TRUE)))
{
error= 1;
thd->bulk_param= save_bulk_param;
break;
}
thd->bulk_param= save_bulk_param;
if (!--limit && using_limit)
{
......@@ -1361,6 +1367,20 @@ int mysql_update(THD *thd,
(ulong) thd->get_stmt_da()->current_statement_warn_count());
my_ok(thd, (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated,
id, buff);
if (thd->get_stmt_da()->is_bulk_op())
{
/*
Update the diagnostics message sent to a client with number of actual
rows update by the statement. For bulk UPDATE operation it should be
done after returning from my_ok() since the final number of updated
rows be knows on finishing the entire bulk update statement.
*/
my_snprintf(buff, sizeof(buff), ER_THD(thd, ER_UPDATE_INFO),
(ulong) thd->get_stmt_da()->affected_rows(),
(ulong) thd->get_stmt_da()->affected_rows(),
(ulong) thd->get_stmt_da()->current_statement_warn_count());
thd->get_stmt_da()->set_message(buff);
}
DBUG_PRINT("info",("%ld records updated", (long) updated));
}
thd->count_cuted_fields= CHECK_FIELD_IGNORE; /* calc cuted fields */
......
......@@ -807,7 +807,7 @@ bool buf_LRU_free_page(buf_page_t *bpage, bool zip)
break;
case 1:
mysql_mutex_lock(&buf_pool.flush_list_mutex);
if (const lsn_t om = bpage->oldest_modification()) {
if (ut_d(const lsn_t om =) bpage->oldest_modification()) {
ut_ad(om == 1);
buf_pool.delete_from_flush_list(bpage);
}
......
......@@ -421,8 +421,7 @@ inline void page_rec_set_n_owned(buf_block_t *block, rec_t *rec, ulint n_owned,
ut_ad(block->page.frame == page_align(rec));
ut_ad(comp == (page_is_comp(block->page.frame) != 0));
if (page_zip_des_t *page_zip= compressed
? buf_block_get_page_zip(block) : nullptr)
if (compressed && is_buf_block_get_page_zip(block))
{
ut_ad(comp);
rec_set_bit_field_1(rec, n_owned, REC_NEW_N_OWNED,
......
......@@ -1822,7 +1822,7 @@ trx_print_low(
/*!< in: mem_heap_get_size(trx->lock.lock_heap) */
{
if (const trx_id_t id = trx->id) {
fprintf(f, "TRANSACTION " TRX_ID_FMT, trx->id);
fprintf(f, "TRANSACTION " TRX_ID_FMT, id);
} else {
fprintf(f, "TRANSACTION (%p)", trx);
}
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment