From 9f50104235ee61ee2ba49b9d25b437ae9d2ebc67 Mon Sep 17 00:00:00 2001 From: Jaeheon Shim Date: Sun, 31 May 2026 12:14:01 -0400 Subject: [PATCH 1/4] MDEV-10426 ANY_VALUE function Implement the ANY_VALUE function that, in a GROUP BY expression, returns any one of the rows as a result. This meets the aggregation requirements of sql_mode=ONLY_FULL_GROUP_BY. Completed as part of Google Summer of Code 2026. Corrected as part of testing: * MDEV-41138 Ensure ANY_VALUE not fully reserved * MDEV-41200 ANY_VALUE not marked BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION * MDEV-41202 ONLY_FULL_GROUP_BY silently bypassed for outer-correlated fields inside aggregate * MDEV-41400 Server is crashing in base_list::push_back/List::push_back --- client/mysql.cc | 1 + mysql-test/main/any_value.result | 170 ++++++++++++++++++ mysql-test/main/any_value.test | 126 +++++++++++++ mysql-test/main/group_by.result | 31 ++++ mysql-test/main/group_by.test | 41 +++++ .../binlog/r/binlog_stm_unsafe_warning.result | 11 ++ .../binlog/t/binlog_stm_unsafe_warning.test | 15 ++ .../suite/perfschema/r/digest_view.result | 50 +++--- .../start_server_low_digest_sql_length.result | 4 +- sql/item.cc | 4 +- sql/item_sum.cc | 51 +++++- sql/item_sum.h | 38 +++- sql/lex.h | 1 + sql/sql_yacc.yy | 17 +- 14 files changed, 523 insertions(+), 37 deletions(-) create mode 100644 mysql-test/main/any_value.result create mode 100644 mysql-test/main/any_value.test diff --git a/client/mysql.cc b/client/mysql.cc index e11c974db4074..cd77a6f62de4c 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -919,6 +919,7 @@ static COMMANDS commands[] = { { "ADDTIME", 0, 0, 0, ""}, { "AES_ENCRYPT", 0, 0, 0, ""}, { "AES_DECRYPT", 0, 0, 0, ""}, + { "ANY_VALUE", 0, 0, 0, ""}, { "AREA", 0, 0, 0, ""}, { "ASIN", 0, 0, 0, ""}, { "ASBINARY", 0, 0, 0, ""}, diff --git a/mysql-test/main/any_value.result b/mysql-test/main/any_value.result new file mode 100644 index 0000000000000..939df29cf3964 --- /dev/null +++ b/mysql-test/main/any_value.result @@ -0,0 +1,170 @@ +# +# MDEV-10426: ANY_VALUE function +# +CREATE TABLE t0 (a INT, b INT); +CREATE TABLE t1 (a INT, b INT); +CREATE TABLE t2 (a INT, b INT); +CREATE TABLE t3 (c INT, d INT); +CREATE TABLE t4 (x INT, y INT, z CHAR(1)); +CREATE TABLE t5 (x INT, y INT, INDEX idx (y, x)); +CREATE TABLE t6 (x INT, y CHAR(1), z INT); +INSERT INTO t0 VALUES (NULL,10),(NULL,10),(NULL,20),(NULL,20),(NULL,30); +INSERT INTO t1 VALUES (NULL,NULL),(NULL,NULL),(NULL,NULL); +INSERT INTO t2 VALUES (1,10),(2,10),(NULL,20),(3,20),(NULL,30),(4,40); +INSERT INTO t3 VALUES (1,100),(2,200),(3,300); +INSERT INTO t4 VALUES (1,10,'a'),(2,10,'a'),(3,20,'b'),(4,20,'b'),(5,30,'c'); +INSERT INTO t5 VALUES (1,10),(2,10),(3,20),(4,20),(5,30); +INSERT INTO t6 VALUES (1,'a',1),(1,'a',2),(1,'b',3),(1,'b',4),(2,'a',5),(2,'a',6),(2,'b',7); +SET @save_sql_mode=@@sql_mode; +SET SQL_MODE=''; +SELECT ANY_VALUE(b) FROM t2; +ANY_VALUE(b) +10 +SELECT b, a FROM t2 GROUP BY b; +b a +10 1 +20 NULL +30 NULL +40 4 +SELECT b, ANY_VALUE(a) FROM t2 GROUP BY b; +b ANY_VALUE(a) +10 1 +20 NULL +30 NULL +40 4 +SET SQL_MODE=ONLY_FULL_GROUP_BY; +SELECT ANY_VALUE(b) FROM t0; +ANY_VALUE(b) +10 +SELECT ANY_VALUE(b) FROM t2; +ANY_VALUE(b) +10 +SELECT COUNT(*), ANY_VALUE(b) FROM t2; +COUNT(*) ANY_VALUE(b) +6 10 +SELECT c FROM t3 WHERE ANY_VALUE(d) = 200; +ERROR HY000: Invalid use of group function +SELECT ANY_VALUE(b) FROM t0 GROUP BY b; +ANY_VALUE(b) +10 +20 +30 +SELECT ANY_VALUE(a), b FROM t2 GROUP BY b; +ANY_VALUE(a) b +1 10 +NULL 20 +NULL 30 +4 40 +SELECT ANY_VALUE(b) FROM t2 GROUP BY b; +ANY_VALUE(b) +10 +20 +30 +40 +SELECT b, ANY_VALUE(a + 100) FROM t2 GROUP BY b; +b ANY_VALUE(a + 100) +10 101 +20 NULL +30 NULL +40 104 +SELECT b, ANY_VALUE(a * 2 + b) FROM t2 GROUP BY b; +b ANY_VALUE(a * 2 + b) +10 12 +20 NULL +30 NULL +40 48 +SELECT ANY_VALUE(a) FROM t0; +ANY_VALUE(a) +NULL +SELECT b, ANY_VALUE(a) FROM t0 GROUP BY b; +b ANY_VALUE(a) +10 NULL +20 NULL +30 NULL +SELECT COUNT(*), ANY_VALUE(a) FROM t0; +COUNT(*) ANY_VALUE(a) +5 NULL +SELECT b, COUNT(*), ANY_VALUE(a) FROM t0 GROUP BY b; +b COUNT(*) ANY_VALUE(a) +10 2 NULL +20 2 NULL +30 1 NULL +SELECT ANY_VALUE(a), ANY_VALUE(b) FROM t1; +ANY_VALUE(a) ANY_VALUE(b) +NULL NULL +SELECT COUNT(*), ANY_VALUE(a) FROM t1; +COUNT(*) ANY_VALUE(a) +3 NULL +SELECT a, ANY_VALUE(b) FROM t1 GROUP BY a; +a ANY_VALUE(b) +NULL NULL +SELECT y, ANY_VALUE(x) FROM t5 GROUP BY y; +y ANY_VALUE(x) +10 1 +20 3 +30 5 +EXPLAIN SELECT y, ANY_VALUE(x) FROM t5 GROUP BY y; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t5 index NULL idx 10 NULL 5 Using index +SELECT b, (SELECT SUM(t3.d) + SUM(t2.a) FROM t3) AS sub FROM t2 GROUP BY b; +b sub +10 603 +20 603 +30 NULL +40 604 +SELECT b, (SELECT SUM(t3.d) + ANY_VALUE(t2.a) FROM t3) AS sub FROM t2 GROUP BY b; +b sub +10 601 +20 NULL +30 NULL +40 604 +SELECT y, ANY_VALUE(z) FROM t4 GROUP BY y HAVING ANY_VALUE(z) = 'b'; +y ANY_VALUE(z) +20 b +SELECT x, y, ANY_VALUE(z) FROM t6 GROUP BY x, y WITH ROLLUP; +x y ANY_VALUE(z) +1 a 1 +1 b 3 +1 NULL 1 +2 a 5 +2 b 7 +2 NULL 5 +NULL NULL 1 +SELECT x, y, ANY_VALUE(z) OVER (PARTITION BY y) AS w FROM t4 ORDER BY x; +x y w +1 10 a +2 10 a +3 20 b +4 20 b +5 30 c +SELECT x, y, ANY_VALUE(z) OVER () AS w FROM t4 ORDER BY x; +x y w +1 10 a +2 10 a +3 20 a +4 20 a +5 30 a +SELECT x, y, ANY_VALUE(z) OVER (PARTITION BY y ORDER BY x) AS w FROM t4 ORDER BY x; +x y w +1 10 a +2 10 a +3 20 b +4 20 b +5 30 c +DROP TABLE t0,t1,t2,t3,t4,t5,t6; +CREATE TABLE t (a CHAR CHARACTER SET latin2); +INSERT INTO t VALUES ('a'),('b'); +SELECT charset(ANY_VALUE(a)), collation(ANY_VALUE(a)) FROM t; +charset(ANY_VALUE(a)) collation(ANY_VALUE(a)) +latin2 latin2_general_ci +SELECT coercibility(ANY_VALUE(a)), coercibility(ANY_VALUE('x')) FROM t; +coercibility(ANY_VALUE(a)) coercibility(ANY_VALUE('x')) +2 6 +DROP TABLE t; +CREATE TABLE t1 (any_value INT); +SELECT 1 AS any_value; +any_value +1 +DROP TABLE t1; +SET sql_mode=@save_sql_mode; +# End of 13.2 tests. diff --git a/mysql-test/main/any_value.test b/mysql-test/main/any_value.test new file mode 100644 index 0000000000000..de3121701b5e4 --- /dev/null +++ b/mysql-test/main/any_value.test @@ -0,0 +1,126 @@ +--echo # +--echo # MDEV-10426: ANY_VALUE function +--echo # + +CREATE TABLE t0 (a INT, b INT); +CREATE TABLE t1 (a INT, b INT); +CREATE TABLE t2 (a INT, b INT); +CREATE TABLE t3 (c INT, d INT); +CREATE TABLE t4 (x INT, y INT, z CHAR(1)); +CREATE TABLE t5 (x INT, y INT, INDEX idx (y, x)); +CREATE TABLE t6 (x INT, y CHAR(1), z INT); +INSERT INTO t0 VALUES (NULL,10),(NULL,10),(NULL,20),(NULL,20),(NULL,30); +INSERT INTO t1 VALUES (NULL,NULL),(NULL,NULL),(NULL,NULL); +INSERT INTO t2 VALUES (1,10),(2,10),(NULL,20),(3,20),(NULL,30),(4,40); +INSERT INTO t3 VALUES (1,100),(2,200),(3,300); +INSERT INTO t4 VALUES (1,10,'a'),(2,10,'a'),(3,20,'b'),(4,20,'b'),(5,30,'c'); +INSERT INTO t5 VALUES (1,10),(2,10),(3,20),(4,20),(5,30); +INSERT INTO t6 VALUES (1,'a',1),(1,'a',2),(1,'b',3),(1,'b',4),(2,'a',5),(2,'a',6),(2,'b',7); + +SET @save_sql_mode=@@sql_mode; +SET SQL_MODE=''; + +SELECT ANY_VALUE(b) FROM t2; + +SELECT b, a FROM t2 GROUP BY b; +SELECT b, ANY_VALUE(a) FROM t2 GROUP BY b; + +SET SQL_MODE=ONLY_FULL_GROUP_BY; + +# +# Without GROUP BY +# + +SELECT ANY_VALUE(b) FROM t0; +SELECT ANY_VALUE(b) FROM t2; + +# Mixing real aggregate function +SELECT COUNT(*), ANY_VALUE(b) FROM t2; + +# In WHERE +--error ER_INVALID_GROUP_FUNC_USE +SELECT c FROM t3 WHERE ANY_VALUE(d) = 200; + +# +# With GROUP BY +# + +SELECT ANY_VALUE(b) FROM t0 GROUP BY b; + +# Regular use in SELECT-list +SELECT ANY_VALUE(a), b FROM t2 GROUP BY b; +SELECT ANY_VALUE(b) FROM t2 GROUP BY b; + +# Expression inside ANY_VALUE +SELECT b, ANY_VALUE(a + 100) FROM t2 GROUP BY b; +SELECT b, ANY_VALUE(a * 2 + b) FROM t2 GROUP BY b; + +# +# NULL handling +# + +SELECT ANY_VALUE(a) FROM t0; +SELECT b, ANY_VALUE(a) FROM t0 GROUP BY b; + +SELECT COUNT(*), ANY_VALUE(a) FROM t0; +SELECT b, COUNT(*), ANY_VALUE(a) FROM t0 GROUP BY b; + +SELECT ANY_VALUE(a), ANY_VALUE(b) FROM t1; +SELECT COUNT(*), ANY_VALUE(a) FROM t1; + +SELECT a, ANY_VALUE(b) FROM t1 GROUP BY a; + +# Table with index on GROUP BY column +SELECT y, ANY_VALUE(x) FROM t5 GROUP BY y; +EXPLAIN SELECT y, ANY_VALUE(x) FROM t5 GROUP BY y; + +# Correlated subquery +SELECT b, (SELECT SUM(t3.d) + SUM(t2.a) FROM t3) AS sub FROM t2 GROUP BY b; + +SELECT b, (SELECT SUM(t3.d) + ANY_VALUE(t2.a) FROM t3) AS sub FROM t2 GROUP BY b; + +# In HAVING +SELECT y, ANY_VALUE(z) FROM t4 GROUP BY y HAVING ANY_VALUE(z) = 'b'; + +# Rollup +SELECT x, y, ANY_VALUE(z) FROM t6 GROUP BY x, y WITH ROLLUP; + +# +# As a window function +# + +# NOTE: When used as a window function, ANY_VALUE()'s return value can vary +# across executions. The internal iteration order of the temp table used +# for window computation can depend on the in-memory position of rows, which may +# be different from run to run. Thus, when writing such test cases, it is +# important that the ANY_VALUE column is functionally dependent on the PARTITION +# BY column, else you risk creating flaky tests. + +SELECT x, y, ANY_VALUE(z) OVER (PARTITION BY y) AS w FROM t4 ORDER BY x; +SELECT x, y, ANY_VALUE(z) OVER () AS w FROM t4 ORDER BY x; +SELECT x, y, ANY_VALUE(z) OVER (PARTITION BY y ORDER BY x) AS w FROM t4 ORDER BY x; + +DROP TABLE t0,t1,t2,t3,t4,t5,t6; + +# +# Charset/Collation/Coercibility Tests +# + +CREATE TABLE t (a CHAR CHARACTER SET latin2); +INSERT INTO t VALUES ('a'),('b'); + +# Charset/Collation preserved + +SELECT charset(ANY_VALUE(a)), collation(ANY_VALUE(a)) FROM t; +SELECT coercibility(ANY_VALUE(a)), coercibility(ANY_VALUE('x')) FROM t; + +DROP TABLE t; + +# Ensure ANY_VALUE is not a fully reserved word +CREATE TABLE t1 (any_value INT); +SELECT 1 AS any_value; +DROP TABLE t1; + +SET sql_mode=@save_sql_mode; + +--echo # End of 13.2 tests. diff --git a/mysql-test/main/group_by.result b/mysql-test/main/group_by.result index d33b36d053106..622c1e4a25935 100644 --- a/mysql-test/main/group_by.result +++ b/mysql-test/main/group_by.result @@ -3205,3 +3205,34 @@ we BPYFY BPYFY we c c DROP TABLE t1, t2; # End of 11.8 tests +# +# MDEV-41202 ONLY_FULL_GROUP_BY silently bypassed for outer-correlated fields inside aggregate +# +SET sql_mode='ONLY_FULL_GROUP_BY'; +CREATE TABLE t0 (a INT, b INT, c INT); +CREATE TABLE t1 (b INT); +INSERT INTO t0 VALUES (1,10,100),(1,20,200),(2,30,300); +INSERT INTO t1 VALUES (1000); +# here error as expected: +SELECT (SELECT sum(t0.b + t1.b) FROM t1) AS s, t0.c FROM t0 GROUP BY t0.a; +ERROR 42000: 'test.t0.b' isn't in GROUP BY +# here error is also expected: +SELECT t0.a, (SELECT sum(t0.b + t1.b) FROM t1) AS s FROM t0 GROUP BY t0.a; +ERROR 42000: 'test.t0.b' isn't in GROUP BY +SELECT t0.a, (SELECT any_value(t0.b + t1.b) FROM t1) AS s FROM t0 GROUP BY t0.a; +ERROR 42000: 'test.t0.b' isn't in GROUP BY +DROP TABLE t0, t1; +# +# MDEV-41400 Server is crashing in base_list::push_back/List::push_back +# +create table t1 (a int primary key, b int); +insert into t1 values (1,1); +create table t2 (c int); +insert into t2 values (1),(2); +insert into t1 values (1,1) on duplicate key update b=(select max(t2.c + t1.b) from t2); +select * from t1; +a b +1 3 +drop table t2, t1; +SET sql_mode=DEFAULT; +# End of 13.2 tests diff --git a/mysql-test/main/group_by.test b/mysql-test/main/group_by.test index c14647314dae0..a5c0cad7f74f6 100644 --- a/mysql-test/main/group_by.test +++ b/mysql-test/main/group_by.test @@ -2278,3 +2278,44 @@ DROP TABLE t1, t2; --echo # End of 11.8 tests +--echo # +--echo # MDEV-41202 ONLY_FULL_GROUP_BY silently bypassed for outer-correlated fields inside aggregate +--echo # + +SET sql_mode='ONLY_FULL_GROUP_BY'; + +CREATE TABLE t0 (a INT, b INT, c INT); +CREATE TABLE t1 (b INT); +INSERT INTO t0 VALUES (1,10,100),(1,20,200),(2,30,300); +INSERT INTO t1 VALUES (1000); + +--echo # here error as expected: +--error 1055 +SELECT (SELECT sum(t0.b + t1.b) FROM t1) AS s, t0.c FROM t0 GROUP BY t0.a; + +--echo # here error is also expected: + +--error 1055 +SELECT t0.a, (SELECT sum(t0.b + t1.b) FROM t1) AS s FROM t0 GROUP BY t0.a; + +--error 1055 +SELECT t0.a, (SELECT any_value(t0.b + t1.b) FROM t1) AS s FROM t0 GROUP BY t0.a; + +DROP TABLE t0, t1; + +--echo # +--echo # MDEV-41400 Server is crashing in base_list::push_back/List::push_back +--echo # + +create table t1 (a int primary key, b int); +insert into t1 values (1,1); +create table t2 (c int); +insert into t2 values (1),(2); +insert into t1 values (1,1) on duplicate key update b=(select max(t2.c + t1.b) from t2); +select * from t1; + +drop table t2, t1; + +SET sql_mode=DEFAULT; + +--echo # End of 13.2 tests diff --git a/mysql-test/suite/binlog/r/binlog_stm_unsafe_warning.result b/mysql-test/suite/binlog/r/binlog_stm_unsafe_warning.result index 971fae6208ff3..13223db125e42 100644 --- a/mysql-test/suite/binlog/r/binlog_stm_unsafe_warning.result +++ b/mysql-test/suite/binlog/r/binlog_stm_unsafe_warning.result @@ -118,3 +118,14 @@ Level Code Message DROP FUNCTION sf_bug50192; DROP TRIGGER tr_bug50192; DROP TABLE t1, t2, t3, t4; +# +# MDEV-41200 ANY_VALUE not marked BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION +# +CREATE TABLE t1 (a int); +INSERT INTO t1 VALUES (1),(2),(3); +CREATE TABLE t2 (a int); +INSERT INTO t2 SELECT ANY_VALUE(a) FROM t1; +Warnings: +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave +DROP TABLE t1, t2; +# End of 13.2 test diff --git a/mysql-test/suite/binlog/t/binlog_stm_unsafe_warning.test b/mysql-test/suite/binlog/t/binlog_stm_unsafe_warning.test index 578f0ff5fc82f..41b292387dde7 100644 --- a/mysql-test/suite/binlog/t/binlog_stm_unsafe_warning.test +++ b/mysql-test/suite/binlog/t/binlog_stm_unsafe_warning.test @@ -206,3 +206,18 @@ SHOW WARNINGS; DROP FUNCTION sf_bug50192; DROP TRIGGER tr_bug50192; DROP TABLE t1, t2, t3, t4; + +--echo # +--echo # MDEV-41200 ANY_VALUE not marked BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION +--echo # + +CREATE TABLE t1 (a int); +INSERT INTO t1 VALUES (1),(2),(3); + +CREATE TABLE t2 (a int); + +INSERT INTO t2 SELECT ANY_VALUE(a) FROM t1; + +DROP TABLE t1, t2; + +--echo # End of 13.2 test diff --git a/mysql-test/suite/perfschema/r/digest_view.result b/mysql-test/suite/perfschema/r/digest_view.result index 4d6bed8b14af9..b321e6fe76333 100644 --- a/mysql-test/suite/perfschema/r/digest_view.result +++ b/mysql-test/suite/perfschema/r/digest_view.result @@ -191,17 +191,17 @@ SELECT SCHEMA_NAME, DIGEST, DIGEST_TEXT, COUNT_STAR FROM performance_schema.events_statements_summary_by_digest ORDER BY DIGEST_TEXT; SCHEMA_NAME DIGEST DIGEST_TEXT COUNT_STAR -test 988dc7e45ffabc03db910c3e42c629f8 EXPLAIN SELECT * FROM `test` . `v1` 1 -test 16b8a4d5ece557635a9b1f3c0a14c5c6 EXPLAIN SELECT * FROM `test` . `v1` WHERE `a` = ? 1 -test 6f8e45939552ec9a2afc56a4736aeb89 EXPLAIN SELECT * FROM `test` . `v1` WHERE `b` > ? 1 -test 27c1844b7807d1b19d3c2dda71a39838 EXPLAIN SELECT `a` , `b` FROM `test` . `v1` 1 -test d452c9a3abcde1d1a1c55aba9ccd1313 EXPLAIN SELECT `b` , `a` FROM `test` . `v1` 1 -test a331d76c1d91a23ec43871e43d5fdce0 SELECT * FROM `test` . `v1` 1 -test c40ea66ff02e22f3b49722aa3630a4bc SELECT * FROM `test` . `v1` WHERE `a` = ? 1 -test 690766296398cc0645cc05cc3da89960 SELECT * FROM `test` . `v1` WHERE `b` > ? 1 -test 8d7fc7fba530b3d0bc14d4a3d8bb0e77 SELECT `a` , `b` FROM `test` . `v1` 1 -test 7b59f6385e43cb116fe91f4088932ab0 SELECT `b` , `a` FROM `test` . `v1` 1 -test c93f430b162118239e9477e7d3e41711 TRUNCATE TABLE `performance_schema` . `events_statements_summary_by_digest` 1 +test 6c7eca87ffa970e2b686de3acf15e604 EXPLAIN SELECT * FROM `test` . `v1` 1 +test b5793bcaeba84b6d931b59fa35a9cf52 EXPLAIN SELECT * FROM `test` . `v1` WHERE `a` = ? 1 +test c673896fb23ba51e584963395c41a3ee EXPLAIN SELECT * FROM `test` . `v1` WHERE `b` > ? 1 +test c75f0bcfd8f30f248b621dde049bb192 EXPLAIN SELECT `a` , `b` FROM `test` . `v1` 1 +test c35fd47f3bca3c8581887fb781f27560 EXPLAIN SELECT `b` , `a` FROM `test` . `v1` 1 +test 1244281593e357646ea9922cb1b31ac4 SELECT * FROM `test` . `v1` 1 +test b8491a4a98eee60c0a847f0a2e8c1819 SELECT * FROM `test` . `v1` WHERE `a` = ? 1 +test 4a71b2e4267848ee4ebfc29d9ca4ad45 SELECT * FROM `test` . `v1` WHERE `b` > ? 1 +test 42035bf426e51794a9e8fd85420702fa SELECT `a` , `b` FROM `test` . `v1` 1 +test 7d5dda25100ead3f838d611f793f3140 SELECT `b` , `a` FROM `test` . `v1` 1 +test ef23939ca43c2fc25b538402f3b2cf73 TRUNCATE TABLE `performance_schema` . `events_statements_summary_by_digest` 1 DROP TABLE test.v1; CREATE VIEW test.v1 AS SELECT * FROM test.t1; EXPLAIN SELECT * from test.v1; @@ -248,19 +248,19 @@ SELECT SCHEMA_NAME, DIGEST, DIGEST_TEXT, COUNT_STAR FROM performance_schema.events_statements_summary_by_digest ORDER BY DIGEST_TEXT; SCHEMA_NAME DIGEST DIGEST_TEXT COUNT_STAR -test 72093b810347cf25618ac951ec648d57 CREATE VIEW `test` . `v1` AS SELECT * FROM `test` . `t1` 1 -test 08b1b52ec3516c71b816600d709be978 DROP TABLE `test` . `v1` 1 -test 988dc7e45ffabc03db910c3e42c629f8 EXPLAIN SELECT * FROM `test` . `v1` 2 -test 16b8a4d5ece557635a9b1f3c0a14c5c6 EXPLAIN SELECT * FROM `test` . `v1` WHERE `a` = ? 2 -test 6f8e45939552ec9a2afc56a4736aeb89 EXPLAIN SELECT * FROM `test` . `v1` WHERE `b` > ? 2 -test 27c1844b7807d1b19d3c2dda71a39838 EXPLAIN SELECT `a` , `b` FROM `test` . `v1` 2 -test d452c9a3abcde1d1a1c55aba9ccd1313 EXPLAIN SELECT `b` , `a` FROM `test` . `v1` 2 -test a331d76c1d91a23ec43871e43d5fdce0 SELECT * FROM `test` . `v1` 2 -test c40ea66ff02e22f3b49722aa3630a4bc SELECT * FROM `test` . `v1` WHERE `a` = ? 2 -test 690766296398cc0645cc05cc3da89960 SELECT * FROM `test` . `v1` WHERE `b` > ? 2 -test bf7946899fcfc7bd266fb2b8930aec03 SELECT SCHEMA_NAME , `DIGEST` , `DIGEST_TEXT` , `COUNT_STAR` FROM `performance_schema` . `events_statements_summary_by_digest` ORDER BY `DIGEST_TEXT` 1 -test 8d7fc7fba530b3d0bc14d4a3d8bb0e77 SELECT `a` , `b` FROM `test` . `v1` 2 -test 7b59f6385e43cb116fe91f4088932ab0 SELECT `b` , `a` FROM `test` . `v1` 2 -test c93f430b162118239e9477e7d3e41711 TRUNCATE TABLE `performance_schema` . `events_statements_summary_by_digest` 1 +test 5008a8995805c952dece5e92c1aa266f CREATE VIEW `test` . `v1` AS SELECT * FROM `test` . `t1` 1 +test e2d56ada1f8b76d98bc1ae006a3986a8 DROP TABLE `test` . `v1` 1 +test 6c7eca87ffa970e2b686de3acf15e604 EXPLAIN SELECT * FROM `test` . `v1` 2 +test b5793bcaeba84b6d931b59fa35a9cf52 EXPLAIN SELECT * FROM `test` . `v1` WHERE `a` = ? 2 +test c673896fb23ba51e584963395c41a3ee EXPLAIN SELECT * FROM `test` . `v1` WHERE `b` > ? 2 +test c75f0bcfd8f30f248b621dde049bb192 EXPLAIN SELECT `a` , `b` FROM `test` . `v1` 2 +test c35fd47f3bca3c8581887fb781f27560 EXPLAIN SELECT `b` , `a` FROM `test` . `v1` 2 +test 1244281593e357646ea9922cb1b31ac4 SELECT * FROM `test` . `v1` 2 +test b8491a4a98eee60c0a847f0a2e8c1819 SELECT * FROM `test` . `v1` WHERE `a` = ? 2 +test 4a71b2e4267848ee4ebfc29d9ca4ad45 SELECT * FROM `test` . `v1` WHERE `b` > ? 2 +test 137b5c236fcf0fd9f742c0fc75d44071 SELECT SCHEMA_NAME , `DIGEST` , `DIGEST_TEXT` , `COUNT_STAR` FROM `performance_schema` . `events_statements_summary_by_digest` ORDER BY `DIGEST_TEXT` 1 +test 42035bf426e51794a9e8fd85420702fa SELECT `a` , `b` FROM `test` . `v1` 2 +test 7d5dda25100ead3f838d611f793f3140 SELECT `b` , `a` FROM `test` . `v1` 2 +test ef23939ca43c2fc25b538402f3b2cf73 TRUNCATE TABLE `performance_schema` . `events_statements_summary_by_digest` 1 DROP VIEW test.v1; DROP TABLE test.t1; diff --git a/mysql-test/suite/perfschema/r/start_server_low_digest_sql_length.result b/mysql-test/suite/perfschema/r/start_server_low_digest_sql_length.result index 3f90362e6f57c..c98e7953e320b 100644 --- a/mysql-test/suite/perfschema/r/start_server_low_digest_sql_length.result +++ b/mysql-test/suite/perfschema/r/start_server_low_digest_sql_length.result @@ -8,5 +8,5 @@ SELECT 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1 #################################### SELECT event_name, digest, digest_text, sql_text FROM events_statements_history_long; event_name digest digest_text sql_text -statement/sql/select d3503e8f046de7e50e73f265867654ff SELECT ? + ? + SELECT ... -statement/sql/truncate 59801403538bc3c5532c8d685efe710e TRUNCATE TABLE truncat... +statement/sql/select 230bcebe6d9fc89976beb2ae8883d5e8 SELECT ? + ? + SELECT ... +statement/sql/truncate 04c2fbfba0a854a0efcc94d15251df44 TRUNCATE TABLE truncat... diff --git a/sql/item.cc b/sql/item.cc index e7b207c08615b..8a6a0c0ec4459 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -6611,6 +6611,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) if (*from_field) { if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY && + !thd->lex->in_sum_func && select->cur_pos_in_select_list != UNDEF_POS) { /* @@ -6620,8 +6621,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) if (select->join) { marker= select->cur_pos_in_select_list; - if (!thd->lex->in_sum_func) - select->join->non_agg_fields.push_back(this, thd->mem_root); + select->join->non_agg_fields.push_back(this, thd->mem_root); } else { diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 305eed59c0d93..a8da8a5304dc0 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -310,13 +310,11 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref) */ in_sum_func->outer_fields.push_back(field, thd->mem_root); } - else + else if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY && sel->join) { sel->set_non_agg_field_used(true); - if (sel->join) - { - sel->join->non_agg_fields.push_back(field, thd->mem_root); - } + sel->join->non_agg_fields.push_back(field, thd->mem_root); + field->marker= sel->cur_pos_in_select_list; } } else if (sel->nest_level > aggr_level) @@ -327,9 +325,10 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref) ER_THD(thd, ER_MIX_OF_GROUP_FUNC_AND_FIELDS), MYF(0)); return TRUE; } - else if (sel->join) + if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY && sel->join) { sel->join->non_agg_fields.push_back(field, thd->mem_root); + field->marker= sel->cur_pos_in_select_list; } } } @@ -2725,6 +2724,46 @@ bool Item_sum_max::add() } +bool Item_sum_any_value::add() +{ + DBUG_ENTER("Item_sum_any_value::add"); + + if (!has_value) + { + value->store(args[0]); + value->cache_value(); + null_value= args[0]->null_value; + has_value= 1; + } + DBUG_RETURN(0); +} + + +void Item_sum_any_value::clear() +{ + DBUG_ENTER("Item_sum_any_value::clear"); + if (!const_item()) + { + value->clear(); + null_value= 1; + has_value= 0; + } + DBUG_VOID_RETURN; +} + + +void Item_sum_any_value::update_field() {} + + +Item *Item_sum_any_value::copy_or_same(THD* thd) +{ + DBUG_ENTER("Item_sum_any_value::copy_or_same"); + Item_sum_any_value *item= new (thd->mem_root) Item_sum_any_value(thd, this); + item->setup_hybrid(thd, args[0], value); + DBUG_RETURN(item); +} + + /* bit_or and bit_and */ longlong Item_sum_bit::val_int() diff --git a/sql/item_sum.h b/sql/item_sum.h index 1f94e71b92fac..1674f20b029b6 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -382,7 +382,7 @@ class Item_sum :public Item_func_or_sum enum Sumfunctype { COUNT_FUNC, COUNT_DISTINCT_FUNC, SUM_FUNC, SUM_DISTINCT_FUNC, AVG_FUNC, - AVG_DISTINCT_FUNC, MIN_FUNC, MAX_FUNC, STD_FUNC, + AVG_DISTINCT_FUNC, ANY_VALUE_FUNC, MIN_FUNC, MAX_FUNC, STD_FUNC, VARIANCE_FUNC, SUM_BIT_FUNC, UDF_SUM_FUNC, GROUP_CONCAT_FUNC, ROW_NUMBER_FUNC, RANK_FUNC, DENSE_RANK_FUNC, PERCENT_RANK_FUNC, CUME_DIST_FUNC, NTILE_FUNC, FIRST_VALUE_FUNC, LAST_VALUE_FUNC, @@ -454,6 +454,7 @@ class Item_sum :public Item_func_or_sum bool is_aggr_sum_func() { switch (sum_func()) { + case ANY_VALUE_FUNC: case COUNT_FUNC: case COUNT_DISTINCT_FUNC: case SUM_FUNC: @@ -1296,6 +1297,41 @@ class Item_sum_max final :public Item_sum_min_max }; +class Item_sum_any_value final : public Item_sum_min_max +{ +public: + Item_sum_any_value(THD *thd, Item *item_par) + : Item_sum_min_max(thd, item_par, 1), has_value(FALSE) + { + } + Item_sum_any_value(THD *thd, Item_sum_any_value *item) + : Item_sum_min_max(thd, item), has_value(item->has_value) + { + } + + bool add() override; + void clear() override; + void update_field() override; + + enum Sumfunctype sum_func() const override { return ANY_VALUE_FUNC; } + LEX_CSTRING func_name_cstring() const override + { + static LEX_CSTRING sum_name= {STRING_WITH_LEN("any_value(")}; + return sum_name; + } + Item *copy_or_same(THD* thd) override; + +protected: + Item *shallow_copy(THD *thd) const override + { + return get_item_copy(thd, this); + } + +private: + bool has_value; +}; + + class Item_sum_bit :public Item_sum_int { public: diff --git a/sql/lex.h b/sql/lex.h index b84d208892ca7..7be6201144291 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -752,6 +752,7 @@ SYMBOL symbols[] = { SYMBOL sql_functions[] = { { "ADDDATE", SYM(ADDDATE_SYM)}, + { "ANY_VALUE", SYM(ANY_VALUE_SYM)}, { "BIT_AND", SYM(BIT_AND)}, { "BIT_OR", SYM(BIT_OR)}, { "BIT_XOR", SYM(BIT_XOR)}, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index baa6d56891edf..95d44307f6ef4 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -507,6 +507,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %token ALTER /* SQL-2003-R */ %token ANALYZE_SYM %token AND_SYM /* SQL-2003-R */ +%token ANY_VALUE_SYM %token ASC /* SQL-2003-N */ %token ASENSITIVE_SYM /* FUTURE-USE */ %token AS /* SQL-2003-R */ @@ -11758,7 +11759,21 @@ sum_expr: ; unfiltered_sum_expr: - AVG_SYM '(' in_sum_expr ')' + ANY_VALUE_SYM '(' in_sum_expr ')' + { + $$= new (thd->mem_root) Item_sum_any_value(thd, $3); + if (unlikely($$ == NULL)) + MYSQL_YYABORT; + Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION); + } + | ANY_VALUE_SYM '(' DISTINCT in_sum_expr ')' + { + $$= new (thd->mem_root) Item_sum_any_value(thd, $4); + if (unlikely($$ == NULL)) + MYSQL_YYABORT; + Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION); + } + | AVG_SYM '(' in_sum_expr ')' { $$= new (thd->mem_root) Item_sum_avg(thd, $3, FALSE); if (unlikely($$ == NULL)) From d55c3cf117f471d597aeecd3d52cd0325f6d0f48 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Mon, 2 Nov 2026 14:15:40 +1100 Subject: [PATCH 2/4] MDEV-41985 ANY_VALUE ignores FILTER Item_sum_any_value::update_field can no-longer be a no-op and if there is a filter, we delegate this to the parent class to record the value of the aggregation otherwise it will have null value if the first value in the any_value(g) group results if it didn't mean the filter criteria. Review: Rex Johnston --- mysql-test/main/any_value.result | 13 +++++++++++++ mysql-test/main/any_value.test | 12 ++++++++++++ sql/item_sum.cc | 11 +++++++++-- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/mysql-test/main/any_value.result b/mysql-test/main/any_value.result index 939df29cf3964..f1931d7d89c28 100644 --- a/mysql-test/main/any_value.result +++ b/mysql-test/main/any_value.result @@ -167,4 +167,17 @@ any_value 1 DROP TABLE t1; SET sql_mode=@save_sql_mode; +# +# MDEV-41985 ANY_VALUE ignores FILTER +# +CREATE TABLE t (a INT, b INT, KEY(b)); +INSERT INTO t VALUES (10,1),(20,1),(15,2),(30,2),(NULL,2),(40,2); +SELECT ANY_VALUE(a) FILTER (WHERE a=20) FROM t; +ANY_VALUE(a) FILTER (WHERE a=20) +20 +SELECT b, ANY_VALUE(a) FILTER (WHERE a>15) FROM t GROUP BY b; +b ANY_VALUE(a) FILTER (WHERE a>15) +1 20 +2 30 +DROP TABLE t; # End of 13.2 tests. diff --git a/mysql-test/main/any_value.test b/mysql-test/main/any_value.test index de3121701b5e4..24f12414e187e 100644 --- a/mysql-test/main/any_value.test +++ b/mysql-test/main/any_value.test @@ -123,4 +123,16 @@ DROP TABLE t1; SET sql_mode=@save_sql_mode; +--echo # +--echo # MDEV-41985 ANY_VALUE ignores FILTER +--echo # + +CREATE TABLE t (a INT, b INT, KEY(b)); +INSERT INTO t VALUES (10,1),(20,1),(15,2),(30,2),(NULL,2),(40,2); + +SELECT ANY_VALUE(a) FILTER (WHERE a=20) FROM t; +SELECT b, ANY_VALUE(a) FILTER (WHERE a>15) FROM t GROUP BY b; + +DROP TABLE t; + --echo # End of 13.2 tests. diff --git a/sql/item_sum.cc b/sql/item_sum.cc index a8da8a5304dc0..a5dfb75558f56 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -2728,7 +2728,7 @@ bool Item_sum_any_value::add() { DBUG_ENTER("Item_sum_any_value::add"); - if (!has_value) + if (!has_value && filter_passed()) { value->store(args[0]); value->cache_value(); @@ -2752,7 +2752,14 @@ void Item_sum_any_value::clear() } -void Item_sum_any_value::update_field() {} +void Item_sum_any_value::update_field() +{ + DBUG_ENTER("Item_sum_any_value::update_field"); + DBUG_ASSERT(!has_value); + if (has_filter()) + Item_sum_min_max::update_field(); + DBUG_VOID_RETURN; +} Item *Item_sum_any_value::copy_or_same(THD* thd) From 1d9b22562bc4be7b21ea788934aca27aecbd014c Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Tue, 3 Nov 2026 11:13:19 +1100 Subject: [PATCH 3/4] MDEV-10426: ANY_VALUE to use constant substitution Like MIN and MAX, ANY_VALUE can take a value from an index and will return the first non-NULL value. --- mysql-test/main/any_value.result | 46 ++++++++++++++++++++++++++++++++ mysql-test/main/any_value.test | 16 +++++++++++ sql/opt_sum.cc | 3 ++- 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/any_value.result b/mysql-test/main/any_value.result index f1931d7d89c28..e29b7e5c75b81 100644 --- a/mysql-test/main/any_value.result +++ b/mysql-test/main/any_value.result @@ -180,4 +180,50 @@ b ANY_VALUE(a) FILTER (WHERE a>15) 1 20 2 30 DROP TABLE t; +# +# MDEV-10426: ANY_VALUE to use constant substitution +# +CREATE TABLE t (a INT, KEY(a)); +INSERT INTO t VALUES (NULL),(1),(2); +EXPLAIN FORMAT=JSON SELECT ANY_VALUE(a) FROM t; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "message": "Select tables optimized away" + } + } +} +SELECT ANY_VALUE(a) FROM t; +ANY_VALUE(a) +1 +EXPLAIN FORMAT=JSON SELECT ANY_VALUE(a) FILTER (WHERE a=2) FROM t; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": "REPLACED", + "nested_loop": [ + { + "table": { + "table_name": "t", + "access_type": "index", + "key": "a", + "key_length": "5", + "used_key_parts": ["a"], + "loops": 1, + "rows": 3, + "cost": "REPLACED", + "filtered": 100, + "using_index": true + } + } + ] + } +} +SELECT ANY_VALUE(a) FILTER (WHERE a=2) FROM t; +ANY_VALUE(a) FILTER (WHERE a=2) +2 +DROP TABLE t; # End of 13.2 tests. diff --git a/mysql-test/main/any_value.test b/mysql-test/main/any_value.test index 24f12414e187e..52077dd3cdd41 100644 --- a/mysql-test/main/any_value.test +++ b/mysql-test/main/any_value.test @@ -135,4 +135,20 @@ SELECT b, ANY_VALUE(a) FILTER (WHERE a>15) FROM t GROUP BY b; DROP TABLE t; +--echo # +--echo # MDEV-10426: ANY_VALUE to use constant substitution +--echo # + +CREATE TABLE t (a INT, KEY(a)); +INSERT INTO t VALUES (NULL),(1),(2); + +--source include/analyze-format.inc +EXPLAIN FORMAT=JSON SELECT ANY_VALUE(a) FROM t; +SELECT ANY_VALUE(a) FROM t; + +--source include/analyze-format.inc +EXPLAIN FORMAT=JSON SELECT ANY_VALUE(a) FILTER (WHERE a=2) FROM t; +SELECT ANY_VALUE(a) FILTER (WHERE a=2) FROM t; + +DROP TABLE t; --echo # End of 13.2 tests. diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index f942a014d484c..63194614a4283 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -236,7 +236,7 @@ static int get_index_max_value(TABLE *table, TABLE_REF *ref, uint range_fl, /** - Substitutes constants for some COUNT(), MIN() and MAX() functions. + Substitutes constants for some COUNT, ANY_VALUE, MIN and MAX functions. @param thd thread handler @param tables list of leaves of join table tree @@ -390,6 +390,7 @@ int opt_sum_query(THD *thd, break; case Item_sum::MIN_FUNC: case Item_sum::MAX_FUNC: + case Item_sum::ANY_VALUE_FUNC: { /* Do not attempt MIN/MAX constant replacement if a FILTER clause From ef9d4960d93899a3b3c0002856ef24e8b02bd61d Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Wed, 4 Nov 2026 17:41:33 +1100 Subject: [PATCH 4/4] MDEV-42013 Assertion `!has_value' failed in Item_sum_any_value::update_field When an early execution takes the Item_sum_any_value::add function the has_value gets set. If the execution plan changes for the second execution the update_field resulting in the has_value debug assertion being hit. Added a Item_sum_any_value::reset_field() to reset the has_value back to false so this test case is covered. Thanks Alice Sherepa for the well found test case and Rex Johnston for review. --- mysql-test/main/func_group_innodb.result | 72 ++++++++++++++++++++++++ mysql-test/main/func_group_innodb.test | 45 +++++++++++++++ sql/item_sum.cc | 9 +++ sql/item_sum.h | 1 + 4 files changed, 127 insertions(+) diff --git a/mysql-test/main/func_group_innodb.result b/mysql-test/main/func_group_innodb.result index 6dcffa02c0f11..dbfa4071d5d89 100644 --- a/mysql-test/main/func_group_innodb.result +++ b/mysql-test/main/func_group_innodb.result @@ -278,6 +278,78 @@ MIN(x.v1) NULL drop table t1; # End of 5.5 tests +# +# MDEV-42013 Assertion `!has_value' failed in Item_sum_any_value::update_field +# +create table t (id int primary key, a int, b int, key(b)) engine=innodb; +insert into t values (1,5,1),(2,50,1),(3,20,1),(4,40,2),(5,30,2),(6,35,2); +analyze table t; +Table Op Msg_type Msg_text +test.t analyze status Engine-independent statistics collected +test.t analyze status OK +explain select b, any_value(a) from t group by b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t index NULL b 5 NULL 6 +prepare s from 'select b, any_value(a) from t group by b'; +execute s; +b any_value(a) +1 5 +2 40 +2nd execution +execute s; +b any_value(a) +1 5 +2 40 +insert into t select seq+10, seq%97, seq%3 from seq_1_to_3000; +analyze table t; +Table Op Msg_type Msg_text +test.t analyze status Engine-independent statistics collected +test.t analyze status OK +explain select b, any_value(a) from t group by b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t ALL NULL NULL NULL NULL 3006 Using temporary; Using filesort +execute s; +b any_value(a) +0 3 +1 5 +2 40 +2nd execution +execute s; +b any_value(a) +0 3 +1 5 +2 40 +truncate table t; +insert into t values (1,5,1),(2,50,1),(3,20,1),(4,40,2),(5,30,2),(6,35,2); +analyze table t; +Table Op Msg_type Msg_text +test.t analyze status Engine-independent statistics collected +test.t analyze status OK +create procedure p() +select b, any_value(a) from t group by b; +call p(); +b any_value(a) +1 5 +2 40 +insert into t select seq+10, seq%97, seq%3 from seq_1_to_3000; +analyze table t; +Table Op Msg_type Msg_text +test.t analyze status Engine-independent statistics collected +test.t analyze status OK +call p(); +b any_value(a) +0 3 +1 5 +2 40 +2nd execution +call p(); +b any_value(a) +0 3 +1 5 +2 40 +drop procedure p; +drop table t; +# End of 12.3 tests set global innodb_stats_persistent= @innodb_stats_persistent_save; set global innodb_stats_persistent_sample_pages= @innodb_stats_persistent_sample_pages_save; diff --git a/mysql-test/main/func_group_innodb.test b/mysql-test/main/func_group_innodb.test index 1e08a881894f4..4038beb9d4552 100644 --- a/mysql-test/main/func_group_innodb.test +++ b/mysql-test/main/func_group_innodb.test @@ -3,6 +3,7 @@ # --source include/have_innodb.inc +--source include/have_sequence.inc set @innodb_stats_persistent_save= @@innodb_stats_persistent; set @innodb_stats_persistent_sample_pages_save= @@ -224,6 +225,50 @@ drop table t1; --echo # End of 5.5 tests +--echo # +--echo # MDEV-42013 Assertion `!has_value' failed in Item_sum_any_value::update_field +--echo # + +create table t (id int primary key, a int, b int, key(b)) engine=innodb; +insert into t values (1,5,1),(2,50,1),(3,20,1),(4,40,2),(5,30,2),(6,35,2); + +analyze table t; +explain select b, any_value(a) from t group by b; + +prepare s from 'select b, any_value(a) from t group by b'; + +execute s; +--echo 2nd execution +execute s; +insert into t select seq+10, seq%97, seq%3 from seq_1_to_3000; + +analyze table t; +explain select b, any_value(a) from t group by b; + +execute s; +--echo 2nd execution +execute s; + +truncate table t; +insert into t values (1,5,1),(2,50,1),(3,20,1),(4,40,2),(5,30,2),(6,35,2); +analyze table t; + +create procedure p() + select b, any_value(a) from t group by b; + +call p(); + +insert into t select seq+10, seq%97, seq%3 from seq_1_to_3000; +analyze table t; +call p(); +--echo 2nd execution +call p(); + +drop procedure p; +drop table t; + +--echo # End of 12.3 tests + set global innodb_stats_persistent= @innodb_stats_persistent_save; set global innodb_stats_persistent_sample_pages= @innodb_stats_persistent_sample_pages_save; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index a5dfb75558f56..5c360534a1302 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -2752,6 +2752,15 @@ void Item_sum_any_value::clear() } +void Item_sum_any_value::reset_field() +{ + DBUG_ENTER("Item_sum_any_value::reset_field"); + Item_sum_min_max::reset_field(); + has_value= false; + DBUG_VOID_RETURN; +} + + void Item_sum_any_value::update_field() { DBUG_ENTER("Item_sum_any_value::update_field"); diff --git a/sql/item_sum.h b/sql/item_sum.h index 1674f20b029b6..e06982e69034e 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -1311,6 +1311,7 @@ class Item_sum_any_value final : public Item_sum_min_max bool add() override; void clear() override; + void reset_field() override; void update_field() override; enum Sumfunctype sum_func() const override { return ANY_VALUE_FUNC; }