Hi hackers,

I used Opus to analyze the new features in PG19, and it found a problem
with the "SELECT simple-expression INTO var" fast path from ce8d5fe0e28.

    create function f1() returns int language sql as 'select 1';
    create function caller() returns bool language plpgsql as $$
    declare v int;
    begin
      select f1() into v;
      return found;
    end $$;
    select caller();
    drop function f1();
    create function f1() returns setof int language sql
      as 'select 1 where false';
    select caller();

The last call gives f on 18 and t on 19. Only the first call after the
change is wrong. The attached .sql has more cases.
It is hard to hit. f1() has to be recreated as set-returning while a
session has caller() cached, for example by an extension update.
I think it is because exec_stmt_execsql() calls exec_eval_expr(), which
falls back to SPI when a replan finds the query is no longer simple.
FOUND is then set as if one row came back.

0001 calls exec_eval_simple_expr() directly and uses the regular SPI
code when it returns false. That is the only time the new branch runs,
so the fast path costs the same. It also removes a doubled 'SQL
statement' context line in errors raised under recursion. 0002 is a
test, it is optional.

It is a regression from 18, but a narrow one, so I will not set the open
items list.

Thanks,
Shihao

Attachment: v1-0001-plpgsql-fix-SELECT-INTO-when-the-expression-is-no.patch
Description: Binary data

Attachment: v1-0002-plpgsql-test-SELECT-INTO-after-a-function-becomes.patch
Description: Binary data

Reply via email to