Always use ReleaseTupleDesc after lookup_rowtype_tupdesc et al.
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 15 Dec 2021 23:58:20 +0000 (18:58 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 15 Dec 2021 23:58:20 +0000 (18:58 -0500)
The API spec for lookup_rowtype_tupdesc previously said you could use
either ReleaseTupleDesc or DecrTupleDescRefCount.  However, the latter
choice means the caller must be certain that the returned tupdesc is
refcounted.  I don't recall right now whether that was always true
when this spec was written, but it's certainly not always true since
we introduced shared record typcaches for parallel workers.  That means
that callers using DecrTupleDescRefCount are dependent on typcache
behavior details that they probably shouldn't be.  Hence, change the API
spec to say that you must call ReleaseTupleDesc, and fix the half-dozen
callers that weren't.

AFAICT this is just future-proofing, there's no live bug here.
So no back-patch.

Per gripe from Chapman Flack.

Discussion: https://postgr.es/m/61B901A4.1050808@anastigmatix.net

src/backend/commands/tablecmds.c
src/backend/executor/execExpr.c
src/backend/parser/parse_utilcmd.c
src/backend/utils/adt/expandedrecord.c
src/backend/utils/cache/typcache.c

index 47b29001d5c0819b32ce1dd6b4b4953288a38a77..bf42587e383440c3adea0202a48110751259b5f8 100644 (file)
@@ -15401,7 +15401,7 @@ ATExecAddOf(Relation rel, const TypeName *ofTypename, LOCKMODE lockmode)
                     errmsg("table \"%s\" has different type for column \"%s\"",
                            RelationGetRelationName(rel), type_attname)));
    }
-   DecrTupleDescRefCount(typeTupleDesc);
+   ReleaseTupleDesc(typeTupleDesc);
 
    /* Any remaining columns at the end of the table had better be dropped. */
    for (; table_attno <= tableTupleDesc->natts; table_attno++)
index 892b4e17e09dfd50c3cc54c5a9bdb33292e788ef..7d343f06787b0cf14127c0ecda0a58a550973204 100644 (file)
@@ -1465,7 +1465,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
                /* find out the number of columns in the composite type */
                tupDesc = lookup_rowtype_tupdesc(fstore->resulttype, -1);
                ncolumns = tupDesc->natts;
-               DecrTupleDescRefCount(tupDesc);
+               ReleaseTupleDesc(tupDesc);
 
                /* create workspace for column values */
                values = (Datum *) palloc(sizeof(Datum) * ncolumns);
index 313d7b6ff022b4a8522dcffcc3779877d0b01951..2d857a301bb6bd2a54fc3e9475e6abb5e323a641 100644 (file)
@@ -1484,7 +1484,7 @@ transformOfType(CreateStmtContext *cxt, TypeName *ofTypename)
        n->location = -1;
        cxt->columns = lappend(cxt->columns, n);
    }
-   DecrTupleDescRefCount(tupdesc);
+   ReleaseTupleDesc(tupdesc);
 
    ReleaseSysCache(tuple);
 }
index e19491ecf74426c44f1c3308c2aa993704eac288..38d5384c00e89fc21ade9f15b3141adbb87ec3d1 100644 (file)
@@ -171,7 +171,7 @@ make_expanded_record_from_typeid(Oid type_id, int32 typmod,
 
        /* If we called lookup_rowtype_tupdesc, release the pin it took */
        if (type_id == RECORDOID)
-           DecrTupleDescRefCount(tupdesc);
+           ReleaseTupleDesc(tupdesc);
    }
    else
    {
@@ -854,7 +854,7 @@ expanded_record_fetch_tupdesc(ExpandedRecordHeader *erh)
        tupdesc->tdrefcount++;
 
        /* Release the pin lookup_rowtype_tupdesc acquired */
-       DecrTupleDescRefCount(tupdesc);
+       ReleaseTupleDesc(tupdesc);
    }
    else
    {
index 70e5c51297d962bb82fd6d6c655caabf4a7527f0..d140ef66552e6635e60cb439440b874b029c36c0 100644 (file)
@@ -1820,8 +1820,11 @@ lookup_rowtype_tupdesc_internal(Oid type_id, int32 typmod, bool noError)
  * for example from record_in().)
  *
  * Note: on success, we increment the refcount of the returned TupleDesc,
- * and log the reference in CurrentResourceOwner.  Caller should call
- * ReleaseTupleDesc or DecrTupleDescRefCount when done using the tupdesc.
+ * and log the reference in CurrentResourceOwner.  Caller must call
+ * ReleaseTupleDesc when done using the tupdesc.  (There are some
+ * cases in which the returned tupdesc is not refcounted, in which
+ * case PinTupleDesc/ReleaseTupleDesc are no-ops; but in these cases
+ * the tupdesc is guaranteed to live till process exit.)
  */
 TupleDesc
 lookup_rowtype_tupdesc(Oid type_id, int32 typmod)