From ee206cb830eff45179afde06c93643210b52b196 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 26 Dec 2019 15:19:39 -0500 Subject: [PATCH] Fix possible loss of sync between rectypeid and underlying PLpgSQL_type. When revalidate_rectypeid() acts to update a stale record type OID in plpgsql's data structures, it fixes the active PLpgSQL_rec struct as well as the PLpgSQL_type struct it references. However, the latter is shared across function executions while the former is not. In a later function execution, the PLpgSQL_rec struct would be reinitialized by copy_plpgsql_datums and would then contain a stale type OID, typically leading to "could not open relation with OID NNNN" errors. revalidate_rectypeid() can easily fix this, fortunately, just by treating typ->typoid as authoritative. Per report and diagnosis from Ashutosh Sharma, though this is not his suggested fix. Back-patch to v11 where this code came in. Discussion: https://postgr.es/m/CAE9k0Pkd4dZwt9J5pS9xhJFWpUtqs05C9xk_GEwPzYdV=GxwWg@mail.gmail.com --- src/pl/plpgsql/src/expected/plpgsql_record.out | 6 ++++++ src/pl/plpgsql/src/pl_exec.c | 11 ++++++++++- src/pl/plpgsql/src/sql/plpgsql_record.sql | 1 + 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/pl/plpgsql/src/expected/plpgsql_record.out b/src/pl/plpgsql/src/expected/plpgsql_record.out index 403c6358b9..cf6089cbb2 100644 --- a/src/pl/plpgsql/src/expected/plpgsql_record.out +++ b/src/pl/plpgsql/src/expected/plpgsql_record.out @@ -476,6 +476,12 @@ select sillyaddtwo(42); 44 (1 row) +select sillyaddtwo(43); + sillyaddtwo +------------- + 45 +(1 row) + -- check access to system columns in a record variable create function sillytrig() returns trigger language plpgsql as $$begin diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index aa88719743..35a37d2501 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -6823,7 +6823,16 @@ revalidate_rectypeid(PLpgSQL_rec *rec) Assert(typ != NULL); if (typ->tcache && typ->tcache->tupDesc_identifier == typ->tupdesc_id) - return; /* known up-to-date */ + { + /* + * Although *typ is known up-to-date, it's possible that rectypeid + * isn't, because *rec is cloned during each function startup from a + * copy that we don't have a good way to update. Hence, forcibly fix + * rectypeid before returning. + */ + rec->rectypeid = typ->typoid; + return; + } /* * typcache entry has suffered invalidation, so re-look-up the type name diff --git a/src/pl/plpgsql/src/sql/plpgsql_record.sql b/src/pl/plpgsql/src/sql/plpgsql_record.sql index e93aeac5b9..128846e610 100644 --- a/src/pl/plpgsql/src/sql/plpgsql_record.sql +++ b/src/pl/plpgsql/src/sql/plpgsql_record.sql @@ -303,6 +303,7 @@ drop table mutable2; select sillyaddtwo(42); -- fail create table mutable2(f0 text, f1 int, f2 text); select sillyaddtwo(42); +select sillyaddtwo(43); -- check access to system columns in a record variable