References:
PL/pgSQL functions: How to return a normal table with multiple columns using an execute statement
Functions with variable number of input parameters
Test for null in function with varying parameters
https://www.postgresql.org/docs/current/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN
https://www.postgresql.org/docs/current/xfunc-overload.html
based on the above reference links you can write a function can take variable number of input arguments and return a table.
Setup.
CREATE TABLE test7 (
col1 text,
col2 text,
col3 text,
col4 timestamp,
col5 timestamp,
col6 int,
col7 text
);
INSERT INTO test7
SELECT
i::text,
(i + 1)::text,
(i % 5)::text,
'2022-11-16 10:00:00'::timestamp + i * INTERVAL '30 minute',
'2022-11-16 10:00:00'::timestamp + i * INTERVAL '60 minute',
(random() * 10)::int,
i::text || '_' || (i % 5)::text
FROM
generate_series(1, 10) _ (i);
function:
CREATE OR REPLACE FUNCTION test7_where (_col1 text DEFAULT NULL, _col2 text DEFAULT NULL, _col3 text DEFAULT NULL, _col4 timestamp DEFAULT NULL, _col5 timestamp DEFAULT NULL, _col6 int DEFAULT NULL, _col7 text DEFAULT NULL)
RETURNS TABLE (
col text,
col2 text,
col3 text,
col4 timestamp,
col5 timestamp,
col6 int,
col7 text
)
AS $func$
DECLARE
_sql text;
BEGIN
_sql := concat_ws(' and ', CASE WHEN $1 IS NOT NULL THEN
'col1 = $1'
END, CASE WHEN $2 IS NOT NULL THEN
'col2 = $2'
END, CASE WHEN $3 IS NOT NULL THEN
'col3 = $3'
END, CASE WHEN $4 IS NOT NULL THEN
'col4 = $4'
END, CASE WHEN $5 IS NOT NULL THEN
'col5 = $5'
END, CASE WHEN $6 IS NOT NULL THEN
'col6 = $6'
END, CASE WHEN $7 IS NOT NULL THEN
'col7 = $7'
END);
RAISE NOTICE '_sql:%', _sql;
RETURN QUERY EXECUTE concat($$
SELECT
* FROM test7
WHERE
$$, _sql)
USING $1, $2, $3, $4, $5, $6, $7;
END
$func$
LANGUAGE plpgsql;
Call it:
SELECT
*
FROM
test7_where (_col4 => '2022-11-16 15:00:00', _col5 => '2022-11-16 20:00:00');
SELECT
*
FROM
test7_where (3::text, 4::text, 3::text, '2022-11-16 11:30:00'::timestamp, '2022-11-16 13:00:00'::timestamp, 8, '3_3'::text);