Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit fe9b7b2

Browse files
committed
Fix plpgsql to re-look-up composite type names at need.
Commit 4b93f57 rearranged things in plpgsql to make it cope better with composite types changing underneath it intra-session. However, I failed to consider the case of a composite type being dropped and recreated entirely. In my defense, the previous coding didn't consider that possibility at all either --- but it would accidentally work so long as you didn't change the type's field list, because the built-at-compile-time list of component variables would then still match the type's new definition. The new coding, however, occasionally tries to re-look-up the type by OID, and then fails to find the dropped type. To fix this, we need to save the TypeName struct, and then redo the type OID lookup from that. Of course that's expensive, so we don't want to do it every time we need the type OID. This can be fixed in the same way that 4b93f57 dealt with changes to composite types' definitions: keep an eye on the type's typcache entry to see if its tupledesc has been invalidated. (Perhaps, at some point, this mechanism should be generalized so it can work for non-composite types too; but for now, plpgsql only tries to cope with intra-session redefinitions of composites.) I'm slightly hesitant to back-patch this into v11, because it changes the contents of struct PLpgSQL_type as well as the signature of plpgsql_build_datatype(), so in principle it could break code that is poking into the innards of plpgsql. However, the only popular extension of that ilk is pldebugger, and it doesn't seem to be affected. Since this is a regression for people who were relying on the old behavior, it seems worth taking the small risk of causing compatibility issues. Per bug #15913 from Daniel Fiori. Back-patch to v11 where 4b93f57 came in. Discussion: https://postgr.es/m/15913-a7e112e16dedcffc@postgresql.org
1 parent bb5ae8f commit fe9b7b2

File tree

7 files changed

+265
-37
lines changed

7 files changed

+265
-37
lines changed

src/backend/utils/cache/typcache.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2116,6 +2116,16 @@ TypeCacheRelCallback(Datum arg, Oid relid)
21162116
if (--typentry->tupDesc->tdrefcount == 0)
21172117
FreeTupleDesc(typentry->tupDesc);
21182118
typentry->tupDesc = NULL;
2119+
2120+
/*
2121+
* Also clear tupDesc_identifier, so that anything watching
2122+
* that will realize that the tupdesc has possibly changed.
2123+
* (Alternatively, we could specify that to detect possible
2124+
* tupdesc change, one must check for tupDesc != NULL as well
2125+
* as tupDesc_identifier being the same as what was previously
2126+
* seen. That seems error-prone.)
2127+
*/
2128+
typentry->tupDesc_identifier = 0;
21192129
}
21202130

21212131
/* Reset equality/comparison/hashing validity information */

src/pl/plpgsql/src/expected/plpgsql_record.out

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,35 @@ alter table mutable drop column f3;
447447
select getf3(null::mutable); -- fails again
448448
ERROR: record "x" has no field "f3"
449449
\set SHOW_CONTEXT errors
450+
-- check behavior with creating/dropping a named rowtype
451+
set check_function_bodies = off; -- else reference to nonexistent type fails
452+
create function sillyaddtwo(int) returns int language plpgsql as
453+
$$ declare r mutable2; begin r.f1 := $1; return r.f1 + 2; end $$;
454+
reset check_function_bodies;
455+
select sillyaddtwo(42); -- fail
456+
ERROR: type "mutable2" does not exist
457+
LINE 1: declare r mutable2; begin r.f1 := $1; return r.f1 + 2; end
458+
^
459+
QUERY: declare r mutable2; begin r.f1 := $1; return r.f1 + 2; end
460+
CONTEXT: compilation of PL/pgSQL function "sillyaddtwo" near line 1
461+
create table mutable2(f1 int, f2 text);
462+
select sillyaddtwo(42);
463+
sillyaddtwo
464+
-------------
465+
44
466+
(1 row)
467+
468+
drop table mutable2;
469+
select sillyaddtwo(42); -- fail
470+
ERROR: type "mutable2" does not exist
471+
CONTEXT: PL/pgSQL function sillyaddtwo(integer) line 1 at assignment
472+
create table mutable2(f0 text, f1 int, f2 text);
473+
select sillyaddtwo(42);
474+
sillyaddtwo
475+
-------------
476+
44
477+
(1 row)
478+
450479
-- check access to system columns in a record variable
451480
create function sillytrig() returns trigger language plpgsql as
452481
$$begin

0 commit comments

Comments
 (0)