1
0
mirror of https://github.com/MariaDB/server.git synced 2026-10-23 18:49:29 +03:00

MDEV-35592 Duplicate entry 'NULL' for key 'key0' with subquery cache

Expression cache lookup is null rejecting, so parameters with NULL
never hit and were inserted into the cache table again and again.
After conversion of the cache to an on-disk table (where NULLs are
equal) such a repeated insert failed with ER_DUP_ENTRY.

Do not store rows which can not be looked up.

On 11.4 the cache is just switched off when the HEAP table is full,
so the test fails only after MDEV-9101 (11.5+, ES 11.4 via MENT-2067).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Oleksandr Byelkin
2026-10-15 10:15:40 +02:00
parent d0164223c5
commit 5c61f8e825
3 changed files with 55 additions and 0 deletions

View File

@@ -3960,5 +3960,25 @@ Note 1981 Aggregate function 'bit_or()' of SELECT #4 belongs to SELECT #3
Note 1276 Field or reference 'd' of SELECT #3 was resolved in SELECT #1
Note 1003 /* select#1 */ select `test`.`t1`.`c` AS `d` from `test`.`t1` join `test`.`t1` where <expr_cache><`test`.`t1`.`c`>((/* select#3 */ select ord(<expr_cache><`test`.`t1`.`c`,bit_or(`test`.`t1`.`c`),bit_or(`test`.`t1`.`c`)>((/* select#4 */ select bit_or(`test`.`t1`.`c`)))) from `test`.`t1` group by `test`.`t1`.`c`))
DROP TABLE t0, t1;
#
# MDEV-35592 ERROR 1062 (23000): Duplicate entry 'NULL' for key 'key0'
# on CONCAT in sub-query
#
CREATE TABLE t1 (a INT);
INSERT INTO t1
WITH RECURSIVE s(n) AS (SELECT 0 UNION ALL SELECT n + 1 FROM s WHERE n < 999)
SELECT n FROM s, (VALUES (1), (2), (3), (4)) AS x ORDER BY n;
INSERT INTO t1 VALUES (NULL), (NULL);
CREATE TABLE t2 (b INT);
INSERT INTO t2 VALUES (1), (2);
SET @save_tmp_table_size= @@tmp_table_size;
SET @save_max_heap_table_size= @@max_heap_table_size;
SET tmp_table_size= 16384, max_heap_table_size= 16384;
SELECT COUNT(*) FROM t1 WHERE (SELECT b FROM t2 WHERE t2.b = t1.a) IS NULL;
COUNT(*)
3994
SET tmp_table_size= @save_tmp_table_size;
SET max_heap_table_size= @save_max_heap_table_size;
DROP TABLE t1, t2;
# End of 11.4 tests
SET optimizer_switch=@save_optimizer_switch;

View File

@@ -1769,6 +1769,29 @@ EXPLAIN EXTENDED SELECT t2.d FROM (SELECT c AS d FROM t1) AS t2 JOIN t1 ON (
DROP TABLE t0, t1;
--echo #
--echo # MDEV-35592 ERROR 1062 (23000): Duplicate entry 'NULL' for key 'key0'
--echo # on CONCAT in sub-query
--echo #
CREATE TABLE t1 (a INT);
INSERT INTO t1
WITH RECURSIVE s(n) AS (SELECT 0 UNION ALL SELECT n + 1 FROM s WHERE n < 999)
SELECT n FROM s, (VALUES (1), (2), (3), (4)) AS x ORDER BY n;
INSERT INTO t1 VALUES (NULL), (NULL);
CREATE TABLE t2 (b INT);
INSERT INTO t2 VALUES (1), (2);
SET @save_tmp_table_size= @@tmp_table_size;
SET @save_max_heap_table_size= @@max_heap_table_size;
SET tmp_table_size= 16384, max_heap_table_size= 16384;
SELECT COUNT(*) FROM t1 WHERE (SELECT b FROM t2 WHERE t2.b = t1.a) IS NULL;
SET tmp_table_size= @save_tmp_table_size;
SET max_heap_table_size= @save_max_heap_table_size;
DROP TABLE t1, t2;
--echo # End of 11.4 tests
SET optimizer_switch=@save_optimizer_switch;

View File

@@ -271,6 +271,18 @@ my_bool Expression_cache_tmptable::put_value(Item *value)
DBUG_RETURN(FALSE);
}
/*
check_value() could not build the lookup key (e.g. NULL in the null
rejecting key part), so such a row would never be found. Do not store
it: duplicates of it are rejected after conversion to an on-disk table,
where NULLs are equal.
*/
if (ref.key_err)
{
DBUG_PRINT("info", ("Key can not be looked up, do not store it"));
DBUG_RETURN(FALSE);
}
*(items.head_ref())= value;
fill_record(table_thd, cache_table, cache_table->field, items, true, true,
true);