Merge 10.11 into 11.0

This commit is contained in:
Marko Mäkelä 2023-11-30 16:20:47 +02:00
commit 0fb897b081
33 changed files with 377 additions and 190 deletions

View file

@ -20,8 +20,6 @@ a RIGHT(b,20)
2 bbbbbbbbbbbbbbbbbbbb
connection default;
SET DEBUG='+d,row_ins_extern_checkpoint';
Warnings:
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
SET DEBUG_SYNC='before_row_ins_extern_latch SIGNAL rec_not_blob WAIT_FOR crash';
ROLLBACK;
BEGIN;
@ -88,8 +86,6 @@ BEGIN;
INSERT INTO t2 VALUES (347);
connection default;
SET DEBUG='+d,row_upd_extern_checkpoint';
Warnings:
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
SET DEBUG_SYNC='before_row_upd_extern SIGNAL have_latch WAIT_FOR crash';
UPDATE t3 SET c=REPEAT('i',3000) WHERE a=2;
connection con2;
@ -126,8 +122,6 @@ BEGIN;
INSERT INTO t2 VALUES (33101);
connection default;
SET DEBUG='+d,row_upd_extern_checkpoint';
Warnings:
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
SET DEBUG_SYNC='after_row_upd_extern SIGNAL have_latch WAIT_FOR crash';
UPDATE t3 SET c=REPEAT('j',3000) WHERE a=2;
connection con2;

View file

@ -92,8 +92,6 @@ ALTER TABLE t1 FORCE, ADD COLUMN k4 int;
connection default;
SET DEBUG_SYNC= 'now WAIT_FOR opened';
SET debug = '+d,row_log_tmpfile_fail';
Warnings:
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
INSERT INTO t1 select NULL,'aaa','bbb' from t480;
INSERT INTO t1 select NULL,'aaaa','bbbb' from t480;
SET DEBUG_SYNC= 'now SIGNAL flushed';

View file

@ -36,16 +36,10 @@ SET DEBUG_DBUG = '+d,innodb_OOM_prepare_inplace_alter';
ALTER TABLE t1 ROW_FORMAT=REDUNDANT, ALGORITHM=INPLACE, LOCK=NONE;
ERROR HY000: Out of memory.
SET SESSION DEBUG = @saved_debug_dbug;
Warnings:
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
SET SESSION DEBUG = '+d,innodb_OOM_inplace_alter';
Warnings:
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
ALTER TABLE t1 ROW_FORMAT=REDUNDANT, ALGORITHM=INPLACE, LOCK=NONE;
ERROR HY000: Out of memory.
SET SESSION DEBUG = @saved_debug_dbug;
Warnings:
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
ALTER TABLE t1 ROW_FORMAT=REDUNDANT, ALGORITHM=INPLACE, LOCK=NONE;
connection default;
SHOW CREATE TABLE t1;

View file

@ -16,8 +16,6 @@ SET @save_dbug = @@debug_dbug;
SET DEBUG_DBUG = '+d,do_page_reorganize,do_lock_reverse_page_reorganize';
insert into t1(f2) values (repeat('+', 100));
SET DEBUG = @save_dbug;
Warnings:
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
commit;
connection con1;
f1

View file

@ -20,8 +20,6 @@ END//
CALL populate_t1;
SET autocommit=1;
SET SESSION debug="+d,fts_instrument_result_cache_limit";
Warnings:
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
ALTER TABLE t1 ADD FULLTEXT INDEX `text_content_idx` (`text_content`);
SELECT FTS_DOC_ID, text_content
FROM t1

View file

@ -1,7 +1,5 @@
create table t1 (i int, g geometry not null, spatial index (g))engine=innodb;
SET SESSION debug="+d,rtree_test_check_count";
Warnings:
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
insert into t1 values (1, POINT(1,1));
insert into t1 values (1, POINT(1.5,1.5));
insert into t1 values (1, POINT(3,3));

View file

@ -408,8 +408,6 @@ update t1 set a=point(5,5), b=point(5,5), c=5 where i < 3;
ERROR 23000: Duplicate entry '5' for key 'c'
rollback;
set session debug="+d,row_mysql_crash_if_error";
Warnings:
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
update t1 set a=point(5,5), b=point(5,5), c=5 where i < 3;
ERROR HY000: Lost connection to server during query
insert into t1 values(5, point(5,5), point(5,5), 5);

View file

@ -44,8 +44,6 @@ count(*)
0
SET @saved_dbug = @@SESSION.debug_dbug;
SET DEBUG='+d,page_copy_rec_list_start_compress_fail';
Warnings:
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
delete from t1;
select count(*) from t1 where MBRWithin(t1.c2, @g1);
count(*)

View file

@ -31,7 +31,5 @@ COUNT(*)
0
ALTER TABLE t1 DROP INDEX idx, ADD SPATIAL INDEX idx3(c2);
SET SESSION debug="+d,row_merge_instrument_log_check_flush";
Warnings:
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
ALTER TABLE t1 DROP INDEX idx3, ADD SPATIAL INDEX idx4(c2), ADD SPATIAL INDEX idx5(c3);
DROP TABLE t1;

View file

@ -0,0 +1,22 @@
@@ -7,7 +7,6 @@
WHERE name LIKE 'wait/synch/rwlock/innodb/%'
AND name!='wait/synch/rwlock/innodb/btr_search_latch' ORDER BY name;
name
-wait/synch/rwlock/innodb/dict_operation_lock
wait/synch/rwlock/innodb/fil_space_latch
wait/synch/rwlock/innodb/lock_latch
wait/synch/rwlock/innodb/trx_i_s_cache_lock
@@ -19,11 +18,13 @@
select name from performance_schema.setup_instruments
where name like "wait/synch/sxlock/%" order by name;
name
+wait/synch/sxlock/innodb/dict_operation_lock
wait/synch/sxlock/innodb/index_tree_rw_lock
SELECT DISTINCT name FROM performance_schema.rwlock_instances
WHERE name LIKE 'wait/synch/sxlock/innodb/%'
ORDER BY name;
name
+wait/synch/sxlock/innodb/dict_operation_lock
wait/synch/sxlock/innodb/index_tree_rw_lock
create table t1(a int) engine=innodb;
begin;

View file

@ -5,6 +5,7 @@
--source include/not_embedded.inc
--source include/have_perfschema.inc
--source include/have_innodb.inc
--source include/maybe_debug.inc
UPDATE performance_schema.setup_instruments SET enabled = 'NO', timed = 'YES';

View file

@ -270,16 +270,12 @@ Variable_name Value
Rpl_semi_sync_master_clients 1
# Test failure of select error .
SET GLOBAL debug = 'd,rpl_semisync_simulate_select_error';
Warnings:
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
INSERT INTO t1 VALUES(3);
connection slave;
connection con1;
# Test failure of pthread_create
SET GLOBAL rpl_semi_sync_master_enabled = 0;
SET GLOBAL debug = 'd,rpl_semisync_simulate_create_thread_failure';
Warnings:
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
SET GLOBAL rpl_semi_sync_master_enabled= ON;
# Test failure of pthread_join
SET GLOBAL rpl_semi_sync_master_enabled= OFF;
@ -287,8 +283,6 @@ SET GLOBAL rpl_semi_sync_master_enabled= OFF;
# Failure on registering semisync slave
#
SET GLOBAL debug= 'd,rpl_semisync_simulate_add_slave_failure';
Warnings:
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
SET GLOBAL rpl_semi_sync_master_enabled= ON;
connection slave;
STOP SLAVE IO_THREAD;
@ -297,8 +291,6 @@ START SLAVE IO_THREAD;
include/wait_for_slave_io_to_start.inc
connection con1;
SET GLOBAL debug='';
Warnings:
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
connection slave;
START SLAVE IO_THREAD;
include/wait_for_slave_io_to_start.inc

View file

@ -1,6 +1,4 @@
set session debug="L";
Warnings:
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
select @@global.debug="1";
@@global.debug="1"
0

View file

@ -38,7 +38,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE
VARIABLE_SCOPE SESSION
VARIABLE_TYPE VARCHAR
VARIABLE_COMMENT Built-in DBUG debugger
VARIABLE_COMMENT Built-in DBUG debugger. Alias for --debug
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL

View file

@ -2284,6 +2284,81 @@ Warnings:
Warning 1292 Incorrect inet6 value: ''
DROP TABLE t1;
#
# MDEV-32879 Server crash in my_decimal::operator= or unexpected ER_DUP_ENTRY upon comparison with INET6 and similar types
#
CREATE TABLE t1 (a CHAR(36) NOT NULL, b INET6 NOT NULL, c DATETIME(6) NOT NULL);
INSERT INTO t1 VALUES ('','::','2000-01-01'),('','::','1900-01-01');
SELECT c + (b = a) AS f, GROUP_CONCAT(c) FROM t1 GROUP BY f;
f GROUP_CONCAT(c)
NULL 2000-01-01 00:00:00.000000,1900-01-01 00:00:00.000000
Warnings:
Warning 1292 Incorrect inet6 value: ''
Warning 1292 Incorrect inet6 value: ''
Warning 1292 Incorrect inet6 value: ''
Warning 1292 Incorrect inet6 value: ''
Warning 1292 Incorrect inet6 value: ''
DROP TABLE t1;
CREATE TABLE t1 (a CHAR(36) NOT NULL, b INET6 NOT NULL, c DATETIME(6) NOT NULL);
INSERT INTO t1 VALUES ('','::','2000-01-01'),('','::','1900-01-01');
SELECT c + (b = a) AS f, COUNT(c) FROM t1 GROUP BY f;
f COUNT(c)
NULL 2
Warnings:
Warning 1292 Incorrect inet6 value: ''
Warning 1292 Incorrect inet6 value: ''
Warning 1292 Incorrect inet6 value: ''
DROP TABLE t1;
CREATE OR REPLACE TABLE t1 (a CHAR(36) NOT NULL, b INET6 NOT NULL, c DATETIME(6) NOT NULL);
INSERT INTO t1 VALUES ('','::','2000-01-01'),('','::','1900-01-01');
SELECT c + (b = a) AS f FROM t1 ORDER BY f;
f
NULL
NULL
Warnings:
Warning 1292 Incorrect inet6 value: ''
Warning 1292 Incorrect inet6 value: ''
Warning 1292 Incorrect inet6 value: ''
Warning 1292 Incorrect inet6 value: ''
DROP TABLE t1;
CREATE OR REPLACE TABLE t1 (a CHAR(36) NOT NULL, b INET6 NOT NULL);
INSERT INTO t1 VALUES ('','::'),('','::');
SELECT 1.00 + (b = a) AS f FROM t1 ORDER BY f;
f
NULL
NULL
Warnings:
Warning 1292 Incorrect inet6 value: ''
Warning 1292 Incorrect inet6 value: ''
Warning 1292 Incorrect inet6 value: ''
Warning 1292 Incorrect inet6 value: ''
SELECT 1.00 + (b BETWEEN a AND '') AS f FROM t1 ORDER BY f;
f
NULL
NULL
Warnings:
Warning 1292 Incorrect inet6 value: ''
Warning 1292 Incorrect inet6 value: ''
Warning 1292 Incorrect inet6 value: ''
Warning 1292 Incorrect inet6 value: ''
Warning 1292 Incorrect inet6 value: ''
Warning 1292 Incorrect inet6 value: ''
Warning 1292 Incorrect inet6 value: ''
Warning 1292 Incorrect inet6 value: ''
SELECT 1.00 + (b IN (a,'')) AS f FROM t1 ORDER BY f;
f
NULL
NULL
Warnings:
Warning 1292 Incorrect inet6 value: ''
Warning 1292 Incorrect inet6 value: ''
Warning 1292 Incorrect inet6 value: ''
Warning 1292 Incorrect inet6 value: ''
Warning 1292 Incorrect inet6 value: ''
Warning 1292 Incorrect inet6 value: ''
Warning 1292 Incorrect inet6 value: ''
Warning 1292 Incorrect inet6 value: ''
DROP TABLE t1;
#
# MDEV-22256 Assertion `length == pack_length()' failed in Field_timestamp_with_dec::sort_string
#
SET sql_mode='';

View file

@ -1675,6 +1675,32 @@ INSERT INTO t1 VALUES ('::');
SELECT * FROM t1 WHERE a IN ('','::1');
DROP TABLE t1;
--echo #
--echo # MDEV-32879 Server crash in my_decimal::operator= or unexpected ER_DUP_ENTRY upon comparison with INET6 and similar types
--echo #
CREATE TABLE t1 (a CHAR(36) NOT NULL, b INET6 NOT NULL, c DATETIME(6) NOT NULL);
INSERT INTO t1 VALUES ('','::','2000-01-01'),('','::','1900-01-01');
SELECT c + (b = a) AS f, GROUP_CONCAT(c) FROM t1 GROUP BY f;
DROP TABLE t1;
CREATE TABLE t1 (a CHAR(36) NOT NULL, b INET6 NOT NULL, c DATETIME(6) NOT NULL);
INSERT INTO t1 VALUES ('','::','2000-01-01'),('','::','1900-01-01');
SELECT c + (b = a) AS f, COUNT(c) FROM t1 GROUP BY f;
DROP TABLE t1;
CREATE OR REPLACE TABLE t1 (a CHAR(36) NOT NULL, b INET6 NOT NULL, c DATETIME(6) NOT NULL);
INSERT INTO t1 VALUES ('','::','2000-01-01'),('','::','1900-01-01');
SELECT c + (b = a) AS f FROM t1 ORDER BY f;
DROP TABLE t1;
CREATE OR REPLACE TABLE t1 (a CHAR(36) NOT NULL, b INET6 NOT NULL);
INSERT INTO t1 VALUES ('','::'),('','::');
SELECT 1.00 + (b = a) AS f FROM t1 ORDER BY f;
SELECT 1.00 + (b BETWEEN a AND '') AS f FROM t1 ORDER BY f;
SELECT 1.00 + (b IN (a,'')) AS f FROM t1 ORDER BY f;
DROP TABLE t1;
--echo #
--echo # MDEV-22256 Assertion `length == pack_length()' failed in Field_timestamp_with_dec::sort_string
--echo #

View file

@ -71,7 +71,7 @@ usage() if ($opt_help); # the help function
if ($opt_host =~ s/:(\d+)$//)
{
$opt_port = $1;
$opt_port = $1;
}
if ($opt_host eq '')
@ -101,7 +101,7 @@ my $prefix= 'mysql';
if (eval {DBI->install_driver("MariaDB")}) {
$dsn ="DBI:MariaDB:;";
$prefix= 'mariadb';
}
}
else {
$dsn = "DBI:mysql:;";
}
@ -229,11 +229,11 @@ sub setpwd
{
$pass = "PASSWORD(". $dbh->quote($pass) . ")";
}
my $uh= "$user@$host";
my $uh= $user."@".$host;
my $sth = $dbh->prepare("set password for $uh =$pass") || die $dbh->errstr;
$sth->execute || die $dbh->errstr;
$sth->finish;
print "The password is set for user $user.\n\n";
print "The password is set for user $uh.\n\n";
}

View file

@ -457,40 +457,6 @@ void Item_bool_func::raise_note_if_key_become_unused(THD *thd, const Item_args &
}
bool Item_func::setup_args_and_comparator(THD *thd, Arg_comparator *cmp)
{
DBUG_ASSERT(arg_count >= 2); // Item_func_nullif has arg_count == 3
if (args[0]->cmp_type() == STRING_RESULT &&
args[1]->cmp_type() == STRING_RESULT)
{
CHARSET_INFO *tmp;
/*
Use charset narrowing only for equalities, as that would allow
to construct ref access.
Non-equality comparisons with constants work without charset narrowing,
the constant gets converted.
Non-equality comparisons with non-constants would need narrowing to
enable range optimizer to handle e.g.
t1.mb3key_col <= const_table.mb4_col
But this doesn't look important.
*/
bool allow_narrowing= MY_TEST(functype()==Item_func::EQ_FUNC ||
functype()==Item_func::EQUAL_FUNC);
if (agg_arg_charsets_for_comparison(&tmp, &args[0], &args[1],
allow_narrowing))
return true;
cmp->m_compare_collation= tmp;
}
// Convert constants when compared to int/year field
DBUG_ASSERT(functype() != LIKE_FUNC);
convert_const_compared_to_int_field(thd);
return cmp->set_cmp_func(thd, this, &args[0], &args[1], true);
}
/*
Comparison operators remove arguments' dependency on PAD_CHAR_TO_FULL_LENGTH
in case of PAD SPACE comparison collations: trailing spaces do not affect
@ -519,8 +485,15 @@ bool Item_bool_rowready_func2::fix_length_and_dec(THD *thd)
if (!args[0] || !args[1])
return FALSE;
Item_args old_args(args[0], args[1]);
if (setup_args_and_comparator(thd, &cmp))
convert_const_compared_to_int_field(thd);
Type_handler_hybrid_field_type tmp;
if (tmp.aggregate_for_comparison(func_name_cstring(), args, 2, false) ||
tmp.type_handler()->Item_bool_rowready_func2_fix_length_and_dec(thd,
this))
{
DBUG_ASSERT(thd->is_error());
return true;
}
raise_note_if_key_become_unused(thd, old_args);
return false;
}
@ -540,21 +513,14 @@ bool Item_bool_rowready_func2::fix_length_and_dec(THD *thd)
*/
int Arg_comparator::set_cmp_func(THD *thd, Item_func_or_sum *owner_arg,
const Type_handler *compare_handler,
Item **a1, Item **a2)
{
owner= owner_arg;
set_null= set_null && owner_arg;
a= a1;
b= a2;
Item *tmp_args[2]= {*a1, *a2};
Type_handler_hybrid_field_type tmp;
if (tmp.aggregate_for_comparison(owner_arg->func_name_cstring(), tmp_args, 2,
false))
{
DBUG_ASSERT(thd->is_error());
return 1;
}
m_compare_handler= tmp.type_handler();
m_compare_handler= compare_handler;
return m_compare_handler->set_comparator_func(thd, this);
}
@ -605,6 +571,14 @@ bool Arg_comparator::set_cmp_func_string(THD *thd)
We must set cmp_collation here as we may be called from for an automatic
generated item, like in natural join.
Allow reinterpted superset as subset.
Use charset narrowing only for equalities, as that would allow
to construct ref access.
Non-equality comparisons with constants work without charset narrowing,
the constant gets converted.
Non-equality comparisons with non-constants would need narrowing to
enable range optimizer to handle e.g.
t1.mb3key_col <= const_table.mb4_col
But this doesn't look important.
*/
bool allow_narrowing= false;
if (owner->type() == Item::FUNC_ITEM)
@ -2812,8 +2786,9 @@ Item_func_nullif::fix_length_and_dec(THD *thd)
fix_char_length(args[2]->max_char_length());
set_maybe_null();
m_arg0= args[0];
if (setup_args_and_comparator(thd, &cmp))
return TRUE;
convert_const_compared_to_int_field(thd);
if (cmp.set_cmp_func(thd, this, &args[0], &args[1], true/*set_null*/))
return true;
/*
A special code for EXECUTE..PREPARE.

View file

@ -57,6 +57,7 @@ class Arg_comparator: public Sql_alloc
// when one of arguments is NULL.
int set_cmp_func(THD *thd, Item_func_or_sum *owner_arg,
const Type_handler *compare_handler,
Item **a1, Item **a2);
int compare_not_null_values(longlong val1, longlong val2)
@ -95,11 +96,24 @@ public:
bool set_cmp_func_decimal(THD *thd);
inline int set_cmp_func(THD *thd, Item_func_or_sum *owner_arg,
Item **a1, Item **a2, bool set_null_arg)
const Type_handler *compare_handler,
Item **a1, Item **a2, bool set_null_arg)
{
set_null= set_null_arg;
return set_cmp_func(thd, owner_arg, a1, a2);
return set_cmp_func(thd, owner_arg, compare_handler, a1, a2);
}
int set_cmp_func(THD *thd, Item_func_or_sum *owner_arg,
Item **a1, Item **a2, bool set_null_arg)
{
Item *tmp_args[2]= { *a1, *a2 };
Type_handler_hybrid_field_type tmp;
if (tmp.aggregate_for_comparison(owner_arg->func_name_cstring(),
tmp_args, 2, false))
return 1;
return set_cmp_func(thd, owner_arg, tmp.type_handler(),
a1, a2, set_null_arg);
}
inline int compare() { return (this->*func)(); }
int compare_string(); // compare args[0] & args[1]
@ -561,9 +575,17 @@ public:
return this;
}
bool fix_length_and_dec(THD *thd) override;
bool fix_length_and_dec_generic(THD *thd,
const Type_handler *compare_handler)
{
DBUG_ASSERT(args == tmp_arg);
return cmp.set_cmp_func(thd, this, compare_handler,
tmp_arg, tmp_arg + 1, true/*set_null*/);
}
int set_cmp_func(THD *thd)
{
return cmp.set_cmp_func(thd, this, tmp_arg, tmp_arg + 1, true);
DBUG_ASSERT(args == tmp_arg);
return cmp.set_cmp_func(thd, this, tmp_arg, tmp_arg + 1, true/*set_null*/);
}
CHARSET_INFO *compare_collation() const override
{ return cmp.compare_collation(); }

View file

@ -388,15 +388,6 @@ public:
}
}
void convert_const_compared_to_int_field(THD *thd);
/**
Prepare arguments and setup a comparator.
Used in Item_func_xxx with two arguments and a comparator,
e.g. Item_bool_func2 and Item_func_nullif.
args[0] or args[1] can be modified:
- converted to character set and collation of the operation
- or replaced to an Item_int_with_ref
*/
bool setup_args_and_comparator(THD *thd, Arg_comparator *cmp);
Item_func *get_item_func() override { return this; }
bool is_simplified_cond_processor(void *arg) override
{ return const_item() && !val_int(); }

View file

@ -1296,9 +1296,14 @@ void Item_sum_min_max::setup_hybrid(THD *thd, Item *item, Item *value_arg)
/* Don't cache value, as it will change */
if (!item->const_item())
arg_cache->set_used_tables(RAND_TABLE_BIT);
DBUG_ASSERT(item->type_handler_for_comparison() ==
value->type_handler_for_comparison());
DBUG_ASSERT(item->type_handler_for_comparison() ==
arg_cache->type_handler_for_comparison());
cmp= new (thd->mem_root) Arg_comparator();
if (cmp)
cmp->set_cmp_func(thd, this, (Item**)&arg_cache, (Item**)&value, FALSE);
cmp->set_cmp_func(thd, this, item->type_handler_for_comparison(),
(Item**)&arg_cache, (Item**)&value, FALSE);
DBUG_VOID_RETURN;
}

View file

@ -5668,6 +5668,14 @@ Type_handler_string_result::Item_func_hybrid_field_type_get_date(
/***************************************************************************/
bool Type_handler::Item_bool_rowready_func2_fix_length_and_dec(THD *thd,
Item_bool_rowready_func2 *func) const
{
return func->fix_length_and_dec_generic(thd, this);
}
/***************************************************************************/
bool Type_handler_numeric::
Item_func_between_fix_length_and_dec(Item_func_between *func) const
{

View file

@ -55,6 +55,7 @@ class Item_hybrid_func;
class Item_func_min_max;
class Item_func_hybrid_field_type;
class Item_bool_func2;
class Item_bool_rowready_func2;
class Item_func_between;
class Item_func_in;
class Item_func_round;
@ -4257,6 +4258,8 @@ public:
}
virtual bool Item_eq_value(THD *thd, const Type_cmp_attributes *attr,
Item *a, Item *b) const= 0;
virtual bool Item_bool_rowready_func2_fix_length_and_dec(THD *thd,
Item_bool_rowready_func2 *func) const;
virtual bool Item_hybrid_func_fix_attributes(THD *thd,
const LEX_CSTRING &name,
Type_handler_hybrid_field_type *,

View file

@ -136,6 +136,21 @@ public:
return Fbt_null(item, false).is_null();
}
/*
Check at fix_fields() time if any of the items can return a nullable
value on conversion to Fbt.
*/
static bool fix_fields_maybe_null_on_conversion_to_fbt(Item **items,
uint count)
{
for (uint i= 0; i < count; i++)
{
if (Fbt::fix_fields_maybe_null_on_conversion_to_fbt(items[i]))
return true;
}
return false;
}
public:
Fbt(Item *item, bool *error, bool warn= true)
@ -1534,6 +1549,16 @@ public:
Fbt_null na(a), nb(b);
return !na.is_null() && !nb.is_null() && !na.cmp(nb);
}
bool Item_bool_rowready_func2_fix_length_and_dec(THD *thd,
Item_bool_rowready_func2 *func) const override
{
if (Type_handler::Item_bool_rowready_func2_fix_length_and_dec(thd, func))
return true;
if (!func->maybe_null() &&
Fbt::fix_fields_maybe_null_on_conversion_to_fbt(func->arguments(), 2))
func->set_maybe_null();
return false;
}
bool Item_hybrid_func_fix_attributes(THD *thd, const LEX_CSTRING &name,
Type_handler_hybrid_field_type *h,
Type_all_attributes *attr,
@ -1715,6 +1740,9 @@ public:
bool Item_func_between_fix_length_and_dec(Item_func_between *func) const override
{
if (!func->maybe_null() &&
Fbt::fix_fields_maybe_null_on_conversion_to_fbt(func->arguments(), 3))
func->set_maybe_null();
return false;
}
longlong Item_func_between_val_int(Item_func_between *func) const override
@ -1737,6 +1765,10 @@ public:
Item_func_in *func)
const override
{
if (!func->maybe_null() &&
Fbt::fix_fields_maybe_null_on_conversion_to_fbt(func->arguments(),
func->argument_count()))
func->set_maybe_null();
if (func->compatible_types_scalar_bisection_possible())
{
return func->value_list_convert_const_to_int(thd) ||

View file

@ -1049,11 +1049,10 @@ static Sys_var_charptr_fscs Sys_datadir(
static Sys_var_dbug Sys_dbug(
"debug", "Built-in DBUG debugger", sys_var::SESSION,
CMD_LINE(OPT_ARG, '#'), DEFAULT(""), NO_MUTEX_GUARD, NOT_IN_BINLOG,
ON_CHECK(check_has_super), ON_UPDATE(0),
DEPRECATED("'@@debug_dbug'")); // since 5.5.37
ON_CHECK(check_has_super));
static Sys_var_dbug Sys_debug_dbug(
"debug_dbug", "Built-in DBUG debugger", sys_var::SESSION,
"debug_dbug", "Built-in DBUG debugger. Alias for --debug", sys_var::SESSION,
CMD_LINE(OPT_ARG, '#'), DEFAULT(""), NO_MUTEX_GUARD, NOT_IN_BINLOG,
ON_CHECK(check_has_super));
#endif

View file

@ -788,7 +788,8 @@ static rec_offs *btr_page_get_parent(rec_offs *offsets, mem_heap_t *heap,
/************************************************************//**
Returns the upper level node pointer to a page. It is assumed that mtr holds
an x-latch on the tree.
@return rec_get_offsets() of the node pointer record */
@return rec_get_offsets() of the node pointer record
@retval nullptr on corruption */
static
rec_offs*
btr_page_get_father_block(
@ -2374,6 +2375,11 @@ btr_attach_half_pages(
offsets = btr_page_get_father_block(nullptr, heap, mtr,
&cursor);
if (UNIV_UNLIKELY(!offsets)) {
mem_heap_free(heap);
return DB_CORRUPTION;
}
/* Replace the address of the old child node (= page) with the
address of the new lower half */
@ -3247,6 +3253,14 @@ btr_lift_page_up(
offsets = btr_page_get_father_block(offsets, heap,
mtr, &cursor);
}
if (UNIV_UNLIKELY(!offsets)) {
parent_corrupted:
mem_heap_free(heap);
*err = DB_CORRUPTION;
return nullptr;
}
father_block = btr_cur_get_block(&cursor);
father_page_zip = buf_block_get_page_zip(father_block);
@ -3272,6 +3286,10 @@ btr_lift_page_up(
&cursor);
}
if (UNIV_UNLIKELY(!offsets)) {
goto parent_corrupted;
}
blocks[n_blocks++] = b = btr_cur_get_block(&cursor);
}
@ -3484,6 +3502,10 @@ get_offsets:
NULL, heap, mtr, &father_cursor);
}
if (UNIV_UNLIKELY(!offsets)) {
goto corrupted;
}
if (adjust) {
nth_rec = page_rec_get_n_recs_before(btr_cur_get_rec(cursor));
if (UNIV_UNLIKELY(!nth_rec || nth_rec == ULINT_UNDEFINED)) {

View file

@ -2414,14 +2414,21 @@ lookup:
if (discard_attempted || !bpage->frame)
{
/* Even when we are holding a hash_lock, it should be
acceptable to wait for a page S-latch here, because
buf_page_t::read_complete() will not wait for buf_pool.mutex,
and because S-latch would not conflict with a U-latch
that would be protecting buf_page_t::write_complete(). */
bpage->lock.s_lock();
const bool got_s_latch= bpage->lock.s_lock_try();
hash_lock.unlock_shared();
break;
if (UNIV_LIKELY(got_s_latch))
break;
/* We may fail to acquire bpage->lock because
buf_page_t::read_complete() may be invoking
buf_pool_t::corrupted_evict() on this block, which it would
hold an exclusive latch on.
Let us aqcuire and release buf_pool.mutex to ensure that any
buf_pool_t::corrupted_evict() will proceed before we reacquire
the hash_lock that it could be waiting for. */
mysql_mutex_lock(&buf_pool.mutex);
mysql_mutex_unlock(&buf_pool.mutex);
goto lookup;
}
hash_lock.unlock_shared();

View file

@ -958,11 +958,12 @@ void dict_sys_t::lock_wait(SRW_LOCK_ARGS(const char *file, unsigned line))
if (latch_ex_wait_start.compare_exchange_strong
(old, now, std::memory_order_relaxed, std::memory_order_relaxed))
{
#ifdef UNIV_DEBUG
latch.x_lock(SRW_LOCK_ARGS(file, line));
#else
latch.wr_lock(SRW_LOCK_ARGS(file, line));
#endif
latch_ex_wait_start.store(0, std::memory_order_relaxed);
ut_ad(!latch_readers);
ut_ad(!latch_ex);
ut_d(latch_ex= pthread_self());
return;
}
@ -977,33 +978,39 @@ void dict_sys_t::lock_wait(SRW_LOCK_ARGS(const char *file, unsigned line))
if (waited > threshold / 4)
ib::warn() << "A long wait (" << waited
<< " seconds) was observed for dict_sys.latch";
#ifdef UNIV_DEBUG
latch.x_lock(SRW_LOCK_ARGS(file, line));
#else
latch.wr_lock(SRW_LOCK_ARGS(file, line));
ut_ad(!latch_readers);
ut_ad(!latch_ex);
ut_d(latch_ex= pthread_self());
#endif
}
#ifdef UNIV_PFS_RWLOCK
ATTRIBUTE_NOINLINE void dict_sys_t::unlock()
{
ut_ad(latch_ex == pthread_self());
ut_ad(!latch_readers);
ut_d(latch_ex= 0);
# ifdef UNIV_DEBUG
latch.x_unlock();
# else
latch.wr_unlock();
# endif
}
ATTRIBUTE_NOINLINE void dict_sys_t::freeze(const char *file, unsigned line)
{
# ifdef UNIV_DEBUG
latch.s_lock(file, line);
# else
latch.rd_lock(file, line);
ut_ad(!latch_ex);
ut_d(latch_readers++);
# endif
}
ATTRIBUTE_NOINLINE void dict_sys_t::unfreeze()
{
ut_ad(!latch_ex);
ut_ad(latch_readers--);
# ifdef UNIV_DEBUG
latch.s_unlock();
# else
latch.rd_unlock();
# endif
}
#endif /* UNIV_PFS_RWLOCK */
@ -4511,7 +4518,11 @@ void dict_sys_t::close()
temp_id_hash.free();
unlock();
#ifdef UNIV_DEBUG
latch.free();
#else
latch.destroy();
#endif
mysql_mutex_destroy(&dict_foreign_err_mutex);

View file

@ -580,7 +580,13 @@ static PSI_rwlock_info all_innodb_rwlocks[] =
# ifdef BTR_CUR_HASH_ADAPT
{ &btr_search_latch_key, "btr_search_latch", 0 },
# endif
{ &dict_operation_lock_key, "dict_operation_lock", 0 },
{ &dict_operation_lock_key, "dict_operation_lock",
# ifdef UNIV_DEBUG
PSI_RWLOCK_FLAG_SX
# else
0
# endif
},
{ &fil_space_latch_key, "fil_space_latch", 0 },
{ &trx_i_s_cache_lock_key, "trx_i_s_cache_lock", 0 },
{ &trx_purge_latch_key, "trx_purge_latch", 0 },
@ -13456,14 +13462,7 @@ int ha_innobase::delete_table(const char *name)
/* FOREIGN KEY constraints cannot exist on partitioned tables. */;
#endif
else
{
dict_sys.freeze(SRW_LOCK_CALL);
for (const dict_foreign_t* f : table->referenced_set)
if (dict_table_t* child= f->foreign_table)
if ((err= lock_table_for_trx(child, trx, LOCK_X)) != DB_SUCCESS)
break;
dict_sys.unfreeze();
}
err= lock_table_children(table, trx);
}
dict_table_t *table_stats= nullptr, *index_stats= nullptr;
@ -13861,14 +13860,7 @@ int ha_innobase::truncate()
dict_table_t *table_stats = nullptr, *index_stats = nullptr;
MDL_ticket *mdl_table = nullptr, *mdl_index = nullptr;
dberr_t error= DB_SUCCESS;
dict_sys.freeze(SRW_LOCK_CALL);
for (const dict_foreign_t *f : ib_table->referenced_set)
if (dict_table_t *child= f->foreign_table)
if ((error= lock_table_for_trx(child, trx, LOCK_X)) != DB_SUCCESS)
break;
dict_sys.unfreeze();
dberr_t error= lock_table_children(ib_table, trx);
if (error == DB_SUCCESS)
error= lock_table_for_trx(ib_table, trx, LOCK_X);
@ -14059,16 +14051,7 @@ ha_innobase::rename_table(
/* There is no need to lock any FOREIGN KEY child tables. */
} else if (dict_table_t *table = dict_table_open_on_name(
norm_from, false, DICT_ERR_IGNORE_FK_NOKEY)) {
dict_sys.freeze(SRW_LOCK_CALL);
for (const dict_foreign_t* f : table->referenced_set) {
if (dict_table_t* child = f->foreign_table) {
error = lock_table_for_trx(child, trx, LOCK_X);
if (error != DB_SUCCESS) {
break;
}
}
}
dict_sys.unfreeze();
error = lock_table_children(table, trx);
if (error == DB_SUCCESS) {
error = lock_table_for_trx(table, trx, LOCK_X);
}
@ -15667,15 +15650,17 @@ ha_innobase::extra(
{
/* Warning: since it is not sure that MariaDB calls external_lock()
before calling this function, m_prebuilt->trx can be obsolete! */
trx_t* trx = check_trx_exists(ha_thd());
trx_t* trx;
switch (operation) {
case HA_EXTRA_FLUSH:
(void)check_trx_exists(ha_thd());
if (m_prebuilt->blob_heap) {
row_mysql_prebuilt_free_blob_heap(m_prebuilt);
}
break;
case HA_EXTRA_RESET_STATE:
trx = check_trx_exists(ha_thd());
reset_template();
trx->duplicates = 0;
stmt_boundary:
@ -15684,18 +15669,23 @@ ha_innobase::extra(
trx->bulk_insert = false;
break;
case HA_EXTRA_NO_KEYREAD:
(void)check_trx_exists(ha_thd());
m_prebuilt->read_just_key = 0;
break;
case HA_EXTRA_KEYREAD:
(void)check_trx_exists(ha_thd());
m_prebuilt->read_just_key = 1;
break;
case HA_EXTRA_KEYREAD_PRESERVE_FIELDS:
(void)check_trx_exists(ha_thd());
m_prebuilt->keep_other_fields_on_keyread = 1;
break;
case HA_EXTRA_INSERT_WITH_UPDATE:
trx = check_trx_exists(ha_thd());
trx->duplicates |= TRX_DUP_IGNORE;
goto stmt_boundary;
case HA_EXTRA_NO_IGNORE_DUP_KEY:
trx = check_trx_exists(ha_thd());
trx->duplicates &= ~TRX_DUP_IGNORE;
if (trx->is_bulk_insert()) {
/* Allow a subsequent INSERT into an empty table
@ -15707,9 +15697,11 @@ ha_innobase::extra(
}
goto stmt_boundary;
case HA_EXTRA_WRITE_CAN_REPLACE:
trx = check_trx_exists(ha_thd());
trx->duplicates |= TRX_DUP_REPLACE;
goto stmt_boundary;
case HA_EXTRA_WRITE_CANNOT_REPLACE:
trx = check_trx_exists(ha_thd());
trx->duplicates &= ~TRX_DUP_REPLACE;
if (trx->is_bulk_insert()) {
/* Allow a subsequent INSERT into an empty table
@ -15718,6 +15710,7 @@ ha_innobase::extra(
}
goto stmt_boundary;
case HA_EXTRA_BEGIN_ALTER_COPY:
trx = check_trx_exists(ha_thd());
m_prebuilt->table->skip_alter_undo = 1;
if (m_prebuilt->table->is_temporary()
|| !m_prebuilt->table->versioned_by_id()) {
@ -15730,6 +15723,7 @@ ha_innobase::extra(
.first->second.set_versioned(0);
break;
case HA_EXTRA_END_ALTER_COPY:
trx = check_trx_exists(ha_thd());
m_prebuilt->table->skip_alter_undo = 0;
if (!m_prebuilt->table->is_temporary()
&& !high_level_read_only) {

View file

@ -11222,16 +11222,7 @@ ha_innobase::commit_inplace_alter_table(
fts_optimize_remove_table(ctx->old_table);
}
dict_sys.freeze(SRW_LOCK_CALL);
for (auto f : ctx->old_table->referenced_set) {
if (dict_table_t* child = f->foreign_table) {
error = lock_table_for_trx(child, trx, LOCK_X);
if (error != DB_SUCCESS) {
break;
}
}
}
dict_sys.unfreeze();
error = lock_table_children(ctx->old_table, trx);
if (ctx->new_table->fts) {
ut_ad(!ctx->new_table->fts->add_wq);

View file

@ -1311,14 +1311,14 @@ class dict_sys_t
/** The my_hrtime_coarse().val of the oldest lock_wait() start, or 0 */
std::atomic<ulonglong> latch_ex_wait_start;
/** the rw-latch protecting the data dictionary cache */
alignas(CPU_LEVEL1_DCACHE_LINESIZE) srw_lock latch;
#ifdef UNIV_DEBUG
/** whether latch is being held in exclusive mode (by any thread) */
Atomic_relaxed<pthread_t> latch_ex;
/** number of S-latch holders */
Atomic_counter<uint32_t> latch_readers;
typedef index_lock dict_lock;
#else
typedef srw_lock dict_lock;
#endif
/** the rw-latch protecting the data dictionary cache */
alignas(CPU_LEVEL1_DCACHE_LINESIZE) dict_lock latch;
public:
/** Indexes of SYS_TABLE[] */
enum
@ -1469,15 +1469,12 @@ public:
}
#ifdef UNIV_DEBUG
/** @return whether any thread (not necessarily the current thread)
is holding the latch; that is, this check may return false
positives */
bool frozen() const { return latch_readers || latch_ex; }
/** @return whether any thread (not necessarily the current thread)
is holding a shared latch */
bool frozen_not_locked() const { return latch_readers; }
/** @return whether the current thread is holding the latch */
bool frozen() const { return latch.have_any(); }
/** @return whether the current thread is holding a shared latch */
bool frozen_not_locked() const { return latch.have_s(); }
/** @return whether the current thread holds the exclusive latch */
bool locked() const { return latch_ex == pthread_self(); }
bool locked() const { return latch.have_x(); }
#endif
private:
/** Acquire the exclusive latch */
@ -1492,13 +1489,11 @@ public:
/** Exclusively lock the dictionary cache. */
void lock(SRW_LOCK_ARGS(const char *file, unsigned line))
{
if (latch.wr_lock_try())
{
ut_ad(!latch_readers);
ut_ad(!latch_ex);
ut_d(latch_ex= pthread_self());
}
else
#ifdef UNIV_DEBUG
if (!latch.x_lock_try())
#else
if (!latch.wr_lock_try())
#endif
lock_wait(SRW_LOCK_ARGS(file, line));
}
@ -1513,24 +1508,29 @@ public:
/** Unlock the data dictionary cache. */
void unlock()
{
ut_ad(latch_ex == pthread_self());
ut_ad(!latch_readers);
ut_d(latch_ex= 0);
# ifdef UNIV_DEBUG
latch.x_unlock();
# else
latch.wr_unlock();
# endif
}
/** Acquire a shared lock on the dictionary cache. */
void freeze()
{
# ifdef UNIV_DEBUG
latch.s_lock();
# else
latch.rd_lock();
ut_ad(!latch_ex);
ut_d(latch_readers++);
# endif
}
/** Release a shared lock on the dictionary cache. */
void unfreeze()
{
ut_ad(!latch_ex);
ut_ad(latch_readers--);
# ifdef UNIV_DEBUG
latch.s_unlock();
# else
latch.rd_unlock();
# endif
}
#endif

View file

@ -438,6 +438,13 @@ dberr_t lock_table_for_trx(dict_table_t *table, trx_t *trx, lock_mode mode,
bool no_wait= false)
MY_ATTRIBUTE((nonnull, warn_unused_result));
/** Lock the child tables of a table.
@param table parent table
@param trx transaction
@return error code */
dberr_t lock_table_children(dict_table_t *table, trx_t *trx)
MY_ATTRIBUTE((nonnull, warn_unused_result));
/** Exclusively lock the data dictionary tables.
@param trx dictionary transaction
@return error code

View file

@ -3940,6 +3940,8 @@ static void lock_table_dequeue(lock_t *in_lock, bool owns_wait_mutex)
dberr_t lock_table_for_trx(dict_table_t *table, trx_t *trx, lock_mode mode,
bool no_wait)
{
ut_ad(!dict_sys.frozen());
mem_heap_t *heap= mem_heap_create(512);
sel_node_t *node= sel_node_create(heap);
que_thr_t *thr= pars_complete_graph_for_exec(node, trx, heap, nullptr);
@ -3976,6 +3978,36 @@ run_again:
return err;
}
/** Lock the child tables of a table.
@param table parent table
@param trx transaction
@return error code */
dberr_t lock_table_children(dict_table_t *table, trx_t *trx)
{
dict_sys.freeze(SRW_LOCK_CALL);
std::vector<dict_table_t*> children;
for (auto f : table->referenced_set)
if (dict_table_t *child= f->foreign_table)
{
child->acquire();
children.emplace_back(child);
}
dict_sys.unfreeze();
dberr_t err= DB_SUCCESS;
for (auto child : children)
if ((err= lock_table_for_trx(child, trx, LOCK_X)) != DB_SUCCESS)
break;
for (auto child : children)
child->release();
return err;
}
/** Exclusively lock the data dictionary tables.
@param trx dictionary transaction
@return error code