On Sat, Oct 3, 2026 at 6:38 PM Matheus Alcantara
<matheusssilv97@gmail.com> 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