Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions client/mysql.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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, ""},
Expand Down
229 changes: 229 additions & 0 deletions mysql-test/main/any_value.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
#
# 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;
#
# 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;
#
# 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.
154 changes: 154 additions & 0 deletions mysql-test/main/any_value.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
--echo #
--echo # MDEV-10426: ANY_VALUE function
--echo #

CREATE TABLE t0 (a INT, b INT);
Comment thread
jaeheonshim marked this conversation as resolved.
Resolved
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;
Comment thread
grooverdan marked this conversation as resolved.
Resolved

# 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 #
--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 #
--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.
Loading