Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Fix possible loss of sync between rectypeid and underlying PLpgSQL_type.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 26 Dec 2019 20:19:39 +0000 (15:19 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 26 Dec 2019 20:19:39 +0000 (15:19 -0500)
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
src/pl/plpgsql/src/pl_exec.c
src/pl/plpgsql/src/sql/plpgsql_record.sql

index 403c6358b9319d659af6d7e2459a915d6f03287f..cf6089cbb219262a44be0a5f2ffe623e60d29b4f 100644 (file)
@@ -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
index a083b03bbf6b8b65ba2db4598accc194709e5792..07e3313852bd4cbbdb3538260928560229708d3a 100644 (file)
@@ -6853,7 +6853,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
index e93aeac5b9aa47f13461a4518ff0c20ec0bec53c..128846e6108231a8a22116da60e03a41e188bf86 100644 (file)
@@ -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