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
