mirror of
https://github.com/postgres/postgres.git
synced 2025-07-05 07:21:24 +03:00
Fix failure to cover scalar-vs-rowtype cases in exec_stmt_return().
In commit 9e3ad1aac5
I modified plpgsql
to use exec_stmt_return's simple-variables fast path in more cases.
However, I overlooked that there are really two different return
conventions in use here, depending on whether estate->retistuple is true,
and the existing fast-path code had only bothered to handle one of them.
So trying to return a scalar in a function returning composite, or vice
versa, could lead to unexpected error messages (typically "cache lookup
failed for type 0") or to a null-pointer-dereference crash.
In the DTYPE_VAR case, we can just throw error if retistuple is true,
corresponding to what happens in the general-expression code path that was
being used previously. (Perhaps someday both of these code paths should
attempt a coercion, but today is not that day.)
In the REC and ROW cases, just hand the problem to exec_eval_datum()
when not retistuple. Also clean up the ROW coding slightly so it looks
more like exec_eval_datum().
The previous commit also caused exec_stmt_return_next() to be used in
more cases, but that code seems to be OK as-is.
Per off-list report from Serge Rielau. This bug is new in 9.5 so no need
to back-patch.
This commit is contained in:
@ -4001,6 +4001,38 @@ $$ language plpgsql;
|
||||
select compos();
|
||||
ERROR: cannot return non-composite value from function returning composite type
|
||||
CONTEXT: PL/pgSQL function compos() line 3 at RETURN
|
||||
-- RETURN variable is a different code path ...
|
||||
create or replace function compos() returns compostype as $$
|
||||
declare x int := 42;
|
||||
begin
|
||||
return x;
|
||||
end;
|
||||
$$ language plpgsql;
|
||||
select * from compos();
|
||||
ERROR: cannot return non-composite value from function returning composite type
|
||||
CONTEXT: PL/pgSQL function compos() line 4 at RETURN
|
||||
drop function compos();
|
||||
-- test: invalid use of composite variable in scalar-returning function
|
||||
create or replace function compos() returns int as $$
|
||||
declare
|
||||
v compostype;
|
||||
begin
|
||||
v := (1, 'hello');
|
||||
return v;
|
||||
end;
|
||||
$$ language plpgsql;
|
||||
select compos();
|
||||
ERROR: invalid input syntax for integer: "(1,hello)"
|
||||
CONTEXT: PL/pgSQL function compos() while casting return value to function's return type
|
||||
-- test: invalid use of composite expression in scalar-returning function
|
||||
create or replace function compos() returns int as $$
|
||||
begin
|
||||
return (1, 'hello')::compostype;
|
||||
end;
|
||||
$$ language plpgsql;
|
||||
select compos();
|
||||
ERROR: invalid input syntax for integer: "(1,hello)"
|
||||
CONTEXT: PL/pgSQL function compos() while casting return value to function's return type
|
||||
drop function compos();
|
||||
drop type compostype;
|
||||
--
|
||||
|
@ -3248,6 +3248,39 @@ $$ language plpgsql;
|
||||
|
||||
select compos();
|
||||
|
||||
-- RETURN variable is a different code path ...
|
||||
create or replace function compos() returns compostype as $$
|
||||
declare x int := 42;
|
||||
begin
|
||||
return x;
|
||||
end;
|
||||
$$ language plpgsql;
|
||||
|
||||
select * from compos();
|
||||
|
||||
drop function compos();
|
||||
|
||||
-- test: invalid use of composite variable in scalar-returning function
|
||||
create or replace function compos() returns int as $$
|
||||
declare
|
||||
v compostype;
|
||||
begin
|
||||
v := (1, 'hello');
|
||||
return v;
|
||||
end;
|
||||
$$ language plpgsql;
|
||||
|
||||
select compos();
|
||||
|
||||
-- test: invalid use of composite expression in scalar-returning function
|
||||
create or replace function compos() returns int as $$
|
||||
begin
|
||||
return (1, 'hello')::compostype;
|
||||
end;
|
||||
$$ language plpgsql;
|
||||
|
||||
select compos();
|
||||
|
||||
drop function compos();
|
||||
drop type compostype;
|
||||
|
||||
|
Reference in New Issue
Block a user