You are confusing SQL cursors with PL/pgSQL cursors, which are similar but not the same. In particular, there is no FETCH FORWARD count in PL/pgSQL:
The direction clause can be any of the variants allowed in the
SQL FETCH command except the ones that can fetch more than one
row; namely, it can be NEXT, PRIOR, FIRST, LAST, ABSOLUTE
count, RELATIVE count, FORWARD, or BACKWARD.
In PL/pgSQL you can only fetch one row at a time and process (or return) it.
There is also a disclaimer in the manual:
Note: This page describes usage of cursors at the SQL command level. If you are trying to use cursors inside a PL/pgSQL function,
the rules are different.
You could open that cursor in PL/pgSQL and loop to return rows. But that's only relevant if you want to fetch multiple distinct pieces from a big cursor to save overhead. Else a plain FOR loop (with automatic cursor) or a simple SELECT with OFFSET and LIMIT are certainly faster. Cursors are primarily meant to be returned to and used by the client:
CREATE OR REPLACE FUNCTION getbatch_ref(_cursor refcursor, _workload_id text)
RETURNS refcursor
LANGUAGE plpgsql AS
$func$
BEGIN
OPEN $1 SCROLL FOR
SELECT id
FROM workload
WHERE workload_id = $2
ORDER BY id;
RETURN $1;
END
$func$;
You can use this function in SQL:
BEGIN;
SELECT getbatch_ref('c', 'foo');
MOVE FORWARD 10 IN c;
FETCH FORWARD 10 FROM c;
ROLLBACK; -- or COMMIT;
You could also just use plain SQL:
BEGIN;
DECLARE c SCROLL CURSOR FOR
SELECT id
FROM workload
WHERE workload_id = 'foo'
ORDER BY id;
-- OPEN c; -- only relevant in plpgsql
-- The PostgreSQL server does not implement an OPEN statement for cursors;
-- a cursor is considered to be open when it is declared.
MOVE FORWARD 10 IN c;
FETCH FORWARD 10 FROM c;
ROLLBACK; -- or COMMIT;
FETCH FORWARD countdid work other than the fact thecountvalue couldn't be dynamic. SoFETCH FORWARD 10would happily return 10 results.