summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2019-12-26 15:19:39 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2019-12-26 15:19:39 -0500
commit4ba4bfaf256c17fe4c8f497924b74eb98241b84f (patch)
tree95347fa250b502dec3d9de03bb1483efb6819f10
parentfbe0232358c14792e1b94b902d0f7a9b55154275 (diff)
downloadpostgresql-4ba4bfaf256c17fe4c8f497924b74eb98241b84f.tar.gz
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
-rw-r--r--src/pl/plpgsql/src/expected/plpgsql_record.out6
-rw-r--r--src/pl/plpgsql/src/pl_exec.c11
-rw-r--r--src/pl/plpgsql/src/sql/plpgsql_record.sql1
3 files changed, 17 insertions, 1 deletions
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 2deb7c0b12..d1775d3615 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -6858,7 +6858,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