Skip to content
Open
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
56 changes: 56 additions & 0 deletions bugfix-swarm/review_scratch/function_plugin_filter.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#
# MDEV-41352 SIGSEGV in Item_field::used_tables on a plugin aggregate
# with FILTER
#
CREATE TABLE t (c INT);
SELECT test_plugin_count(1) FILTER (WHERE c) FROM t;
test_plugin_count(1) FILTER (WHERE c)
0
DROP TABLE t;
CREATE TABLE t (id INT PRIMARY KEY, g INT, v INT);
INSERT INTO t VALUES (1,1,10),(2,1,20),(3,2,30),(4,2,NULL),(5,3,50);
SELECT test_plugin_count(v) FILTER (WHERE v > 15) FROM t;
test_plugin_count(v) FILTER (WHERE v > 15)
3
SELECT count(v) FILTER (WHERE v > 15) AS c,
test_plugin_count(v) FILTER (WHERE v > 15) AS pc,
test_plugin_first(v) FILTER (WHERE v > 15) AS pf
FROM t;
c pc pf
3 3 20
SELECT g, count(v) FILTER (WHERE id > 1) AS c,
test_plugin_count(v) FILTER (WHERE id > 1) AS pc,
test_plugin_first(v) FILTER (WHERE id > 1) AS pf
FROM t GROUP BY g ORDER BY g;
g c pc pf
1 1 1 20
2 1 1 30
3 1 1 50
SELECT count(DISTINCT g) FILTER (WHERE v > 15) AS c,
test_plugin_count(DISTINCT g) FILTER (WHERE v > 15) AS pc
FROM t;
c pc
3 3
SELECT id, count(v) FILTER (WHERE v > 15) OVER w AS c,
test_plugin_count(v) FILTER (WHERE v > 15) OVER w AS pc
FROM t
WINDOW w AS (ORDER BY id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING)
ORDER BY id;
id c pc
1 1 1
2 2 2
3 2 2
4 2 2
5 1 1
SELECT test_plugin_count(v) FILTER (WHERE count(v) > 1) FROM t;
ERROR HY000: Incorrect usage of aggregate function and FILTER
CREATE VIEW v1 AS
SELECT test_plugin_count(v) FILTER (WHERE v > 15) AS pc FROM t;
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select test_plugin_count(`t`.`v`) FILTER(WHERE `t`.`v` > 15) AS `pc` from `t` latin1 latin1_swedish_ci
SELECT * FROM v1;
pc
3
DROP VIEW v1;
DROP TABLE t;
38 changes: 38 additions & 0 deletions bugfix-swarm/review_scratch/function_plugin_filter.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
--source include/have_udf.inc

--echo #
--echo # MDEV-41352 SIGSEGV in Item_field::used_tables on a plugin aggregate
--echo # with FILTER
--echo #

CREATE TABLE t (c INT);
SELECT test_plugin_count(1) FILTER (WHERE c) FROM t;
DROP TABLE t;

CREATE TABLE t (id INT PRIMARY KEY, g INT, v INT);
INSERT INTO t VALUES (1,1,10),(2,1,20),(3,2,30),(4,2,NULL),(5,3,50);
SELECT test_plugin_count(v) FILTER (WHERE v > 15) FROM t;
SELECT count(v) FILTER (WHERE v > 15) AS c,
test_plugin_count(v) FILTER (WHERE v > 15) AS pc,
test_plugin_first(v) FILTER (WHERE v > 15) AS pf
FROM t;
SELECT g, count(v) FILTER (WHERE id > 1) AS c,
test_plugin_count(v) FILTER (WHERE id > 1) AS pc,
test_plugin_first(v) FILTER (WHERE id > 1) AS pf
FROM t GROUP BY g ORDER BY g;
SELECT count(DISTINCT g) FILTER (WHERE v > 15) AS c,
test_plugin_count(DISTINCT g) FILTER (WHERE v > 15) AS pc
FROM t;
SELECT id, count(v) FILTER (WHERE v > 15) OVER w AS c,
test_plugin_count(v) FILTER (WHERE v > 15) OVER w AS pc
FROM t
WINDOW w AS (ORDER BY id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING)
ORDER BY id;
--error ER_WRONG_USAGE
SELECT test_plugin_count(v) FILTER (WHERE count(v) > 1) FROM t;
CREATE VIEW v1 AS
SELECT test_plugin_count(v) FILTER (WHERE v > 15) AS pc FROM t;
SHOW CREATE VIEW v1;
SELECT * FROM v1;
DROP VIEW v1;
DROP TABLE t;
91 changes: 91 additions & 0 deletions bugfix-swarm/review_scratch/function_plugin_filter_rv.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
CREATE TABLE t (id INT PRIMARY KEY, g INT, v INT);
INSERT INTO t VALUES (1,1,10),(2,1,20),(3,2,30),(4,2,NULL),(5,3,50);
CREATE TABLE t2 (x INT);
INSERT INTO t2 VALUES (20),(50);
# prepared statement, executed twice
PREPARE s FROM 'SELECT test_plugin_count(v) FILTER (WHERE v > ?) FROM t';
SET @a=15;
EXECUTE s USING @a;
test_plugin_count(v) FILTER (WHERE v > ?)
3
SET @a=25;
EXECUTE s USING @a;
test_plugin_count(v) FILTER (WHERE v > ?)
2
DEALLOCATE PREPARE s;
# stored procedure called twice
CREATE PROCEDURE p()
BEGIN
SELECT g, test_plugin_count(v) FILTER (WHERE v > 15),
test_plugin_first(v) FILTER (WHERE v > 15) FROM t GROUP BY g ORDER BY g;
END|
CALL p();
g test_plugin_count(v) FILTER (WHERE v > 15) test_plugin_first(v) FILTER (WHERE v > 15)
1 1 20
2 1 30
3 1 50
CALL p();
g test_plugin_count(v) FILTER (WHERE v > 15) test_plugin_first(v) FILTER (WHERE v > 15)
1 1 20
2 1 30
3 1 50
DROP PROCEDURE p;
# subquery in filter
SELECT test_plugin_count(v) FILTER (WHERE v IN (SELECT x FROM t2)) FROM t;
test_plugin_count(v) FILTER (WHERE v IN (SELECT x FROM t2))
2
SELECT count(v) FILTER (WHERE v IN (SELECT x FROM t2)) FROM t;
count(v) FILTER (WHERE v IN (SELECT x FROM t2))
2
# outer reference in filter of subquery aggregate
SELECT id, (SELECT test_plugin_count(x) FILTER (WHERE x > t.v) FROM t2) AS pc,
(SELECT count(x) FILTER (WHERE x > t.v) FROM t2) AS c
FROM t ORDER BY id;
id pc c
1 2 2
2 1 1
3 1 1
4 0 0
5 0 0
# window function in filter -> error
SELECT test_plugin_count(v) FILTER (WHERE row_number() OVER () > 1) FROM t;
ERROR HY000: Incorrect usage of window function and FILTER
# unknown column in filter -> error
SELECT test_plugin_count(v) FILTER (WHERE nosuch > 1) FROM t;
ERROR 42S22: Unknown column 'nosuch' in 'SELECT'
# HAVING and ORDER BY referencing filtered plugin aggregate
SELECT g, test_plugin_count(v) FILTER (WHERE v > 15) AS pc FROM t GROUP BY g
HAVING test_plugin_count(v) FILTER (WHERE v > 15) > 0 ORDER BY pc DESC, g;
g pc
1 1
2 1
3 1
# window, filtered first over sliding frame
SELECT id, test_plugin_first(v) FILTER (WHERE v > 15) OVER (ORDER BY id) AS pf,
test_plugin_count(v) FILTER (WHERE id <> 3) OVER (ORDER BY id ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS pc,
count(v) FILTER (WHERE id <> 3) OVER (ORDER BY id ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS c
FROM t ORDER BY id;
id pf pc c
1 NULL 1 1
2 20 2 2
3 20 2 2
4 20 1 1
5 20 1 1
# ROLLUP
SELECT g, test_plugin_count(v) FILTER (WHERE v > 15) AS pc, count(v) FILTER (WHERE v > 15) AS c FROM t GROUP BY g WITH ROLLUP;
g pc c
1 1 1
2 1 1
3 1 1
NULL 3 3
# CREATE TABLE ... SELECT
CREATE TABLE t3 AS SELECT test_plugin_count(v) FILTER (WHERE v > 15) AS pc FROM t;
SELECT * FROM t3;
pc
3
DROP TABLE t3;
# filter always false / empty
SELECT test_plugin_count(v) FILTER (WHERE 0), test_plugin_first(v) FILTER (WHERE 0) FROM t;
test_plugin_count(v) FILTER (WHERE 0) test_plugin_first(v) FILTER (WHERE 0)
0 NULL
DROP TABLE t, t2;
66 changes: 66 additions & 0 deletions bugfix-swarm/review_scratch/function_plugin_filter_rv.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
--source include/have_udf.inc

CREATE TABLE t (id INT PRIMARY KEY, g INT, v INT);
INSERT INTO t VALUES (1,1,10),(2,1,20),(3,2,30),(4,2,NULL),(5,3,50);
CREATE TABLE t2 (x INT);
INSERT INTO t2 VALUES (20),(50);

--echo # prepared statement, executed twice
PREPARE s FROM 'SELECT test_plugin_count(v) FILTER (WHERE v > ?) FROM t';
SET @a=15;
EXECUTE s USING @a;
SET @a=25;
EXECUTE s USING @a;
DEALLOCATE PREPARE s;

--echo # stored procedure called twice
DELIMITER |;
CREATE PROCEDURE p()
BEGIN
SELECT g, test_plugin_count(v) FILTER (WHERE v > 15),
test_plugin_first(v) FILTER (WHERE v > 15) FROM t GROUP BY g ORDER BY g;
END|
DELIMITER ;|
CALL p();
CALL p();
DROP PROCEDURE p;

--echo # subquery in filter
SELECT test_plugin_count(v) FILTER (WHERE v IN (SELECT x FROM t2)) FROM t;
SELECT count(v) FILTER (WHERE v IN (SELECT x FROM t2)) FROM t;

--echo # outer reference in filter of subquery aggregate
SELECT id, (SELECT test_plugin_count(x) FILTER (WHERE x > t.v) FROM t2) AS pc,
(SELECT count(x) FILTER (WHERE x > t.v) FROM t2) AS c
FROM t ORDER BY id;

--echo # window function in filter -> error
--error ER_WRONG_USAGE
SELECT test_plugin_count(v) FILTER (WHERE row_number() OVER () > 1) FROM t;

--echo # unknown column in filter -> error
--error ER_BAD_FIELD_ERROR
SELECT test_plugin_count(v) FILTER (WHERE nosuch > 1) FROM t;

--echo # HAVING and ORDER BY referencing filtered plugin aggregate
SELECT g, test_plugin_count(v) FILTER (WHERE v > 15) AS pc FROM t GROUP BY g
HAVING test_plugin_count(v) FILTER (WHERE v > 15) > 0 ORDER BY pc DESC, g;

--echo # window, filtered first over sliding frame
SELECT id, test_plugin_first(v) FILTER (WHERE v > 15) OVER (ORDER BY id) AS pf,
test_plugin_count(v) FILTER (WHERE id <> 3) OVER (ORDER BY id ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS pc,
count(v) FILTER (WHERE id <> 3) OVER (ORDER BY id ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS c
FROM t ORDER BY id;

--echo # ROLLUP
SELECT g, test_plugin_count(v) FILTER (WHERE v > 15) AS pc, count(v) FILTER (WHERE v > 15) AS c FROM t GROUP BY g WITH ROLLUP;

--echo # CREATE TABLE ... SELECT
CREATE TABLE t3 AS SELECT test_plugin_count(v) FILTER (WHERE v > 15) AS pc FROM t;
SELECT * FROM t3;
DROP TABLE t3;

--echo # filter always false / empty
SELECT test_plugin_count(v) FILTER (WHERE 0), test_plugin_first(v) FILTER (WHERE 0) FROM t;

DROP TABLE t, t2;
9 changes: 9 additions & 0 deletions include/mysql/plugin_function.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,15 @@

/*
API for function plugins. (MariaDB_FUNCTION_PLUGIN)

An aggregate function's Create_func must create an Item_sum_plugin descendant.
Aggregate implementations consume rows in add_row() and use aggregation_arg()
to read values, including values replayed by DISTINCT. FILTER (WHERE ...) is
applied by the server: add_row() and remove_row() see only passing rows.
DISTINCT does not guarantee replay order; order-sensitive implementations
must override supports_distinct() to return false. Aggregates can implement
supports_removal() and remove_row() for moving window frames, and
val_native() to preserve a pluggable result type.
*/
#define MariaDB_FUNCTION_INTERFACE_VERSION (MYSQL_VERSION_ID << 8)

Expand Down
Loading
Loading