mirror of
https://github.com/postgres/postgres.git
synced 2026-03-20 09:36:10 -04:00
Add support function requests for estimating the selectivity, cost, and number of result rows (if a SRF) of the target function. The lack of a way to estimate selectivity of a boolean-returning function in WHERE has been a recognized deficiency of the planner since Berkeley days. This commit finally fixes it. In addition, non-constant estimates of cost and number of output rows are now possible. We still fall back to looking at procost and prorows if the support function doesn't service the request, of course. To make concrete use of the possibility of estimating output rowcount for SRFs, this commit adds support functions for array_unnest(anyarray) and the integer variants of generate_series; the lack of plausible rowcount estimates for those, even when it's obvious to a human, has been a repeated subject of complaints. Obviously, much more could now be done in this line, but I'm mostly just trying to get the infrastructure in place. Discussion: https://postgr.es/m/15193.1548028093@sss.pgh.pa.us
63 lines
2.1 KiB
PL/PgSQL
63 lines
2.1 KiB
PL/PgSQL
--
|
|
-- num_nulls()
|
|
--
|
|
|
|
SELECT num_nonnulls(NULL);
|
|
SELECT num_nonnulls('1');
|
|
SELECT num_nonnulls(NULL::text);
|
|
SELECT num_nonnulls(NULL::text, NULL::int);
|
|
SELECT num_nonnulls(1, 2, NULL::text, NULL::point, '', int8 '9', 1.0 / NULL);
|
|
SELECT num_nonnulls(VARIADIC '{1,2,NULL,3}'::int[]);
|
|
SELECT num_nonnulls(VARIADIC '{"1","2","3","4"}'::text[]);
|
|
SELECT num_nonnulls(VARIADIC ARRAY(SELECT CASE WHEN i <> 40 THEN i END FROM generate_series(1, 100) i));
|
|
|
|
SELECT num_nulls(NULL);
|
|
SELECT num_nulls('1');
|
|
SELECT num_nulls(NULL::text);
|
|
SELECT num_nulls(NULL::text, NULL::int);
|
|
SELECT num_nulls(1, 2, NULL::text, NULL::point, '', int8 '9', 1.0 / NULL);
|
|
SELECT num_nulls(VARIADIC '{1,2,NULL,3}'::int[]);
|
|
SELECT num_nulls(VARIADIC '{"1","2","3","4"}'::text[]);
|
|
SELECT num_nulls(VARIADIC ARRAY(SELECT CASE WHEN i <> 40 THEN i END FROM generate_series(1, 100) i));
|
|
|
|
-- special cases
|
|
SELECT num_nonnulls(VARIADIC NULL::text[]);
|
|
SELECT num_nonnulls(VARIADIC '{}'::int[]);
|
|
SELECT num_nulls(VARIADIC NULL::text[]);
|
|
SELECT num_nulls(VARIADIC '{}'::int[]);
|
|
|
|
-- should fail, one or more arguments is required
|
|
SELECT num_nonnulls();
|
|
SELECT num_nulls();
|
|
|
|
--
|
|
-- Test adding a support function to a subject function
|
|
--
|
|
|
|
CREATE FUNCTION my_int_eq(int, int) RETURNS bool
|
|
LANGUAGE internal STRICT IMMUTABLE PARALLEL SAFE
|
|
AS $$int4eq$$;
|
|
|
|
-- By default, planner does not think that's selective
|
|
EXPLAIN (COSTS OFF)
|
|
SELECT * FROM tenk1 a JOIN tenk1 b ON a.unique1 = b.unique1
|
|
WHERE my_int_eq(a.unique2, 42);
|
|
|
|
-- With support function that knows it's int4eq, we get a different plan
|
|
ALTER FUNCTION my_int_eq(int, int) SUPPORT test_support_func;
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
SELECT * FROM tenk1 a JOIN tenk1 b ON a.unique1 = b.unique1
|
|
WHERE my_int_eq(a.unique2, 42);
|
|
|
|
-- Also test non-default rowcount estimate
|
|
CREATE FUNCTION my_gen_series(int, int) RETURNS SETOF integer
|
|
LANGUAGE internal STRICT IMMUTABLE PARALLEL SAFE
|
|
AS $$generate_series_int4$$
|
|
SUPPORT test_support_func;
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
SELECT * FROM tenk1 a JOIN my_gen_series(1,1000) g ON a.unique1 = g;
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
SELECT * FROM tenk1 a JOIN my_gen_series(1,10) g ON a.unique1 = g;
|