On Sat, Oct 3, 2026 at 6:38 PM Matheus Alcantara
<[email protected]> wrote:
> So 0003 declares the remote cursor before
> synchronizing the remote savepoint level, and raises the error only if
> the current remote depth is deeper than the level of the local cursor.

There is another case 0003 misses: parameter evaluation
can open a remote savepoint after create_cursor() checks the depth.

With 0001 and 0003 on REL_19_STABLE at a2148471, run this in a fresh
cursor_min database. Pass its socket directory and port as psql
variables sock and port:

create extension postgres_fdw;

create table t (id int);
insert into t values (1);

create server s foreign data wrapper postgres_fdw options (dbname
'cursor_min', host :'sock', port :'port');
create user mapping for current_user server s;
create foreign table ft (id int) server s options (table_name 't',
fetch_size '1');
create foreign table fa (id int) server s options (table_name 't');

begin;
declare c cursor for select * from ft where id = (select id from fa limit 1);
savepoint sp;
fetch c;
rollback to sp;
fetch c;
commit;

With 0001 alone, the first fetch is rejected by its depth check. With
0003, it returns 1, but the second fetch fails after rollback: cursor
"c2" does not exist. On clean REL_19_STABLE, the second fetch returns
no rows and commit succeeds.

The subquery becomes an initplan for the outer scan's $1 parameter.
process_query_params() runs it after the depth check. Its scan opens a
remote savepoint, so the outer cursor is declared inside it and removed
by rollback to sp.

Nik


Reply via email to