]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Add all required calls to TupleDescFinalize()
authorDavid Rowley <drowley@postgresql.org>
Sun, 15 Mar 2026 22:45:49 +0000 (11:45 +1300)
committerDavid Rowley <drowley@postgresql.org>
Sun, 15 Mar 2026 22:45:49 +0000 (11:45 +1300)
As of this commit all TupleDescs must have TupleDescFinalize() called on
them once the TupleDesc is set up and before BlessTupleDesc() is called.

In this commit, TupleDescFinalize() does nothing. This change has only
been separated out from the commit that properly implements this function
to make the change more obvious.  Any extension which makes its own
TupleDesc will need to be modified to call the new function.

The follow-up commit which properly implements TupleDescFinalize() will
cause any code which forgets to do this to fail in assert-enabled builds in
BlessTupleDesc().  It may still be worth mentioning this change in the
release notes so that extension authors update their code.

Author: David Rowley <dgrowleyml@gmail.com>
Reviewed-by: Chao Li <li.evan.chao@gmail.com>
Reviewed-by: Andres Freund <andres@anarazel.de>
Reviewed-by: John Naylor <johncnaylorls@gmail.com>
Reviewed-by: Amit Langote <amitlangote09@gmail.com>
Reviewed-by: Zsolt Parragi <zsolt.parragi@percona.com>
Reviewed-by: Álvaro Herrera <alvherre@kurilemu.de>
Reviewed-by: Junwang Zhao <zhjwpku@gmail.com>
Discussion: https://postgr.es/m/CAApHDvpoFjaj3%2Bw_jD5uPnGazaw41A71tVJokLDJg2zfcigpMQ%40mail.gmail.com

39 files changed:
contrib/dblink/dblink.c
contrib/pg_buffercache/pg_buffercache_pages.c
contrib/pg_visibility/pg_visibility.c
src/backend/access/brin/brin_tuple.c
src/backend/access/common/tupdesc.c
src/backend/access/gin/ginutil.c
src/backend/access/gist/gistscan.c
src/backend/access/spgist/spgutils.c
src/backend/access/transam/twophase.c
src/backend/access/transam/xlogfuncs.c
src/backend/backup/basebackup_copy.c
src/backend/catalog/index.c
src/backend/catalog/pg_publication.c
src/backend/catalog/toasting.c
src/backend/commands/explain.c
src/backend/commands/functioncmds.c
src/backend/commands/sequence.c
src/backend/commands/tablecmds.c
src/backend/commands/wait.c
src/backend/executor/execSRF.c
src/backend/executor/execTuples.c
src/backend/executor/nodeFunctionscan.c
src/backend/parser/parse_relation.c
src/backend/parser/parse_target.c
src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
src/backend/replication/walsender.c
src/backend/utils/adt/acl.c
src/backend/utils/adt/genfile.c
src/backend/utils/adt/lockfuncs.c
src/backend/utils/adt/orderedsetaggs.c
src/backend/utils/adt/pgstatfuncs.c
src/backend/utils/adt/tsvector_op.c
src/backend/utils/cache/relcache.c
src/backend/utils/fmgr/funcapi.c
src/backend/utils/misc/guc_funcs.c
src/include/access/tupdesc.h
src/pl/plpgsql/src/pl_comp.c
src/test/modules/test_custom_stats/test_custom_fixed_stats.c
src/test/modules/test_predtest/test_predtest.c

index 2498d80c8e7df9775eee90aade05dcf16347f511..4038950a6efd8fe422dc0065f04fb611d73e090c 100644 (file)
@@ -881,6 +881,7 @@ materializeResult(FunctionCallInfo fcinfo, PGconn *conn, PGresult *res)
                tupdesc = CreateTemplateTupleDesc(1);
                TupleDescInitEntry(tupdesc, (AttrNumber) 1, "status",
                                                   TEXTOID, -1, 0);
+               TupleDescFinalize(tupdesc);
                ntuples = 1;
                nfields = 1;
        }
@@ -1044,6 +1045,7 @@ materializeQueryResult(FunctionCallInfo fcinfo,
                        tupdesc = CreateTemplateTupleDesc(1);
                        TupleDescInitEntry(tupdesc, (AttrNumber) 1, "status",
                                                           TEXTOID, -1, 0);
+                       TupleDescFinalize(tupdesc);
                        attinmeta = TupleDescGetAttInMetadata(tupdesc);
 
                        oldcontext = MemoryContextSwitchTo(rsinfo->econtext->ecxt_per_query_memory);
@@ -1529,6 +1531,8 @@ dblink_get_pkey(PG_FUNCTION_ARGS)
                TupleDescInitEntry(tupdesc, (AttrNumber) 2, "colname",
                                                   TEXTOID, -1, 0);
 
+               TupleDescFinalize(tupdesc);
+
                /*
                 * Generate attribute metadata needed later to produce tuples from raw
                 * C strings
index 89b8685524318a0a280f3a1da6d27ba7718a1832..a6b4fb5252bb1cffc4cc09cb871dd7b0e92b6b5d 100644 (file)
@@ -174,6 +174,7 @@ pg_buffercache_pages(PG_FUNCTION_ARGS)
                        TupleDescInitEntry(tupledesc, (AttrNumber) 9, "pinning_backends",
                                                           INT4OID, -1, 0);
 
+               TupleDescFinalize(tupledesc);
                fctx->tupdesc = BlessTupleDesc(tupledesc);
 
                /* Allocate NBuffers worth of BufferCachePagesRec records. */
@@ -442,6 +443,7 @@ pg_buffercache_os_pages_internal(FunctionCallInfo fcinfo, bool include_numa)
                TupleDescInitEntry(tupledesc, (AttrNumber) 3, "numa_node",
                                                   INT4OID, -1, 0);
 
+               TupleDescFinalize(tupledesc);
                fctx->tupdesc = BlessTupleDesc(tupledesc);
                fctx->include_numa = include_numa;
 
index 9bc3a784bf7c09033364c1a393f5a8a6180fc13e..dfab0b64cf50baabf7a7baedbeda31189188b6b6 100644 (file)
@@ -469,6 +469,8 @@ pg_visibility_tupdesc(bool include_blkno, bool include_pd)
                TupleDescInitEntry(tupdesc, ++a, "pd_all_visible", BOOLOID, -1, 0);
        Assert(a == maxattr);
 
+       TupleDescFinalize(tupdesc);
+
        return BlessTupleDesc(tupdesc);
 }
 
index 69c233c62eb4779bd9c5600634983605a66b5f61..742ac089a28428ba45bb25d11d98d78c25faaaf6 100644 (file)
@@ -84,6 +84,7 @@ brtuple_disk_tupdesc(BrinDesc *brdesc)
 
                MemoryContextSwitchTo(oldcxt);
 
+               TupleDescFinalize(tupdesc);
                brdesc->bd_disktdesc = tupdesc;
        }
 
index b69d10f0a45b364a7f60da176b56d044b06547b1..2137385a833e09bdcc70cf2f6c7814f41fd24108 100644 (file)
@@ -221,6 +221,9 @@ CreateTupleDesc(int natts, Form_pg_attribute *attrs)
                memcpy(TupleDescAttr(desc, i), attrs[i], ATTRIBUTE_FIXED_PART_SIZE);
                populate_compact_attribute(desc, i);
        }
+
+       TupleDescFinalize(desc);
+
        return desc;
 }
 
@@ -265,6 +268,8 @@ CreateTupleDescCopy(TupleDesc tupdesc)
        desc->tdtypeid = tupdesc->tdtypeid;
        desc->tdtypmod = tupdesc->tdtypmod;
 
+       TupleDescFinalize(desc);
+
        return desc;
 }
 
@@ -311,6 +316,8 @@ CreateTupleDescTruncatedCopy(TupleDesc tupdesc, int natts)
        desc->tdtypeid = tupdesc->tdtypeid;
        desc->tdtypmod = tupdesc->tdtypmod;
 
+       TupleDescFinalize(desc);
+
        return desc;
 }
 
@@ -396,6 +403,8 @@ CreateTupleDescCopyConstr(TupleDesc tupdesc)
        desc->tdtypeid = tupdesc->tdtypeid;
        desc->tdtypmod = tupdesc->tdtypmod;
 
+       TupleDescFinalize(desc);
+
        return desc;
 }
 
@@ -438,6 +447,8 @@ TupleDescCopy(TupleDesc dst, TupleDesc src)
         * source's refcount would be wrong in any case.)
         */
        dst->tdrefcount = -1;
+
+       TupleDescFinalize(dst);
 }
 
 /*
@@ -1065,6 +1076,8 @@ BuildDescFromLists(const List *names, const List *types, const List *typmods, co
                TupleDescInitEntryCollation(desc, attnum, attcollation);
        }
 
+       TupleDescFinalize(desc);
+
        return desc;
 }
 
index ff927279cc39a4d78cf0afcb40ee763593a475be..fe7b984ff32369f3ea0d72ee080a3ee0d14d661b 100644 (file)
@@ -129,6 +129,7 @@ initGinState(GinState *state, Relation index)
                                                           attr->attndims);
                        TupleDescInitEntryCollation(state->tupdesc[i], (AttrNumber) 2,
                                                                                attr->attcollation);
+                       TupleDescFinalize(state->tupdesc[i]);
                }
 
                /*
index f23bc4a675707e16b5a1bfc28bb9d916426dc068..c65f93abdaeb8a22c94f37447ce2bc8448b1469f 100644 (file)
@@ -201,6 +201,7 @@ gistrescan(IndexScanDesc scan, ScanKey key, int nkeys,
                                                                                         attno - 1)->atttypid,
                                                           -1, 0);
                }
+               TupleDescFinalize(so->giststate->fetchTupdesc);
                scan->xs_hitupdesc = so->giststate->fetchTupdesc;
 
                /* Also create a memory context that will hold the returned tuples */
index 9f5379b87acbf4339fdef4a41846363ac7644075..b246e8127dbac9641292477f800261ea1a44f3fa 100644 (file)
@@ -340,6 +340,7 @@ getSpGistTupleDesc(Relation index, SpGistTypeDesc *keyType)
                        TupleDescCompactAttr(outTupDesc, i)->attcacheoff = -1;
 
                populate_compact_attribute(outTupDesc, spgKeyColumn);
+               TupleDescFinalize(outTupDesc);
        }
        return outTupDesc;
 }
index 55b9f38927d5280d1845cd1570e5c4b51f09a75e..d468c9774b3ccab1ae49f1d3ef84e083d6885e24 100644 (file)
@@ -745,6 +745,7 @@ pg_prepared_xact(PG_FUNCTION_ARGS)
                TupleDescInitEntry(tupdesc, (AttrNumber) 5, "dbid",
                                                   OIDOID, -1, 0);
 
+               TupleDescFinalize(tupdesc);
                funcctx->tuple_desc = BlessTupleDesc(tupdesc);
 
                /*
index ecb3c8c082015860d1915681811fd4598739cde1..4e35311b2f357fb7f4930e66677fc6d0feef1ca2 100644 (file)
@@ -430,6 +430,7 @@ pg_walfile_name_offset(PG_FUNCTION_ARGS)
        TupleDescInitEntry(resultTupleDesc, (AttrNumber) 2, "file_offset",
                                           INT4OID, -1, 0);
 
+       TupleDescFinalize(resultTupleDesc);
        resultTupleDesc = BlessTupleDesc(resultTupleDesc);
 
        /*
index 07f58b39d8c7882ea1a439e4fdd9d26a5cf0ff67..6c3453efd80a57bb15515e8dd62286840343fe40 100644 (file)
@@ -357,6 +357,8 @@ SendXlogRecPtrResult(XLogRecPtr ptr, TimeLineID tli)
         */
        TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 2, "tli", INT8OID, -1, 0);
 
+       TupleDescFinalize(tupdesc);
+
        /* send RowDescription */
        tstate = begin_tup_output_tupdesc(dest, tupdesc, &TTSOpsVirtual);
 
@@ -388,6 +390,7 @@ SendTablespaceList(List *tablespaces)
        TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 1, "spcoid", OIDOID, -1, 0);
        TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 2, "spclocation", TEXTOID, -1, 0);
        TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 3, "size", INT8OID, -1, 0);
+       TupleDescFinalize(tupdesc);
 
        /* send RowDescription */
        tstate = begin_tup_output_tupdesc(dest, tupdesc, &TTSOpsVirtual);
index 5ee6389d39c47b33bd4910ed70d81038b0eb8d01..0e93ababa87a42c31db347624bd88a2a713d028f 100644 (file)
@@ -481,6 +481,8 @@ ConstructTupleDescriptor(Relation heapRelation,
                populate_compact_attribute(indexTupDesc, i);
        }
 
+       TupleDescFinalize(indexTupDesc);
+
        return indexTupDesc;
 }
 
index aadc7c202c68f2c8b26d9e74e1efb221449ca3d7..a79157c43bf5e005d993975c5624b89e529e639f 100644 (file)
@@ -1322,6 +1322,7 @@ pg_get_publication_tables(PG_FUNCTION_ARGS)
                TupleDescInitEntry(tupdesc, (AttrNumber) 4, "qual",
                                                   PG_NODE_TREEOID, -1, 0);
 
+               TupleDescFinalize(tupdesc);
                funcctx->tuple_desc = BlessTupleDesc(tupdesc);
                funcctx->user_fctx = table_infos;
 
index c78dcea98c1f81c738922be65aec4e3aae9c16b7..078a1cf512745a0dd069528b123d5c0f87140909 100644 (file)
@@ -229,6 +229,12 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
        TupleDescAttr(tupdesc, 1)->attcompression = InvalidCompressionMethod;
        TupleDescAttr(tupdesc, 2)->attcompression = InvalidCompressionMethod;
 
+       populate_compact_attribute(tupdesc, 0);
+       populate_compact_attribute(tupdesc, 1);
+       populate_compact_attribute(tupdesc, 2);
+
+       TupleDescFinalize(tupdesc);
+
        /*
         * Toast tables for regular relations go in pg_toast; those for temp
         * relations go into the per-backend temp-toast-table namespace.
index 93918a223b8d700f71eb934d741191977ec55925..5f922c3f5c2b4bd8876c469772cbcca7925acaf9 100644 (file)
@@ -281,6 +281,7 @@ ExplainResultDesc(ExplainStmt *stmt)
        tupdesc = CreateTemplateTupleDesc(1);
        TupleDescInitEntry(tupdesc, (AttrNumber) 1, "QUERY PLAN",
                                           result_type, -1, 0);
+       TupleDescFinalize(tupdesc);
        return tupdesc;
 }
 
index 242372b1e686eb854172e246467f52cb1c3043fd..3afd762e9dccf2ef9ce37be0da21c3992beaab8b 100644 (file)
@@ -2424,6 +2424,7 @@ CallStmtResultDesc(CallStmt *stmt)
                                                           -1,
                                                           0);
                }
+               TupleDescFinalize(tupdesc);
        }
 
        return tupdesc;
index e1b808bbb6050fead372c5596fa277d3b0995c2b..551667650ba63d2d0dd9e73dca3d8036fb363c07 100644 (file)
@@ -1808,6 +1808,7 @@ pg_get_sequence_data(PG_FUNCTION_ARGS)
                                           BOOLOID, -1, 0);
        TupleDescInitEntry(resultTupleDesc, (AttrNumber) 3, "page_lsn",
                                           LSNOID, -1, 0);
+       TupleDescFinalize(resultTupleDesc);
        resultTupleDesc = BlessTupleDesc(resultTupleDesc);
 
        seqrel = try_relation_open(relid, AccessShareLock);
index cd6d720386f4315eb051ad82c23ed7b69b2e6346..a2e3b72f15616af95f4a1c90e8cd551ed8e67257 100644 (file)
@@ -1038,6 +1038,8 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
                }
        }
 
+       TupleDescFinalize(descriptor);
+
        /*
         * For relations with table AM and partitioned tables, select access
         * method to use: an explicitly indicated one, or (in the case of a
@@ -1466,6 +1468,8 @@ BuildDescForRelation(const List *columns)
                populate_compact_attribute(desc, attnum - 1);
        }
 
+       TupleDescFinalize(desc);
+
        return desc;
 }
 
index 1290df10c6f0c7d35fc9f287a7ee2eb3e3999a73..8e920a723723f58b7dd98ca3632ec6e8ecbd6c36 100644 (file)
@@ -338,5 +338,6 @@ WaitStmtResultDesc(WaitStmt *stmt)
        tupdesc = CreateTemplateTupleDesc(1);
        TupleDescInitEntry(tupdesc, (AttrNumber) 1, "status",
                                           TEXTOID, -1, 0);
+       TupleDescFinalize(tupdesc);
        return tupdesc;
 }
index a0b111dc0e400711c0df209481a4549da14700de..b481e50acfb8982a911601a9da5775bea78d7ae1 100644 (file)
@@ -272,6 +272,7 @@ ExecMakeTableFunctionResult(SetExprState *setexpr,
                                                                           funcrettype,
                                                                           -1,
                                                                           0);
+                                       TupleDescFinalize(tupdesc);
                                        rsinfo.setDesc = tupdesc;
                                }
                                MemoryContextSwitchTo(oldcontext);
@@ -776,6 +777,7 @@ init_sexpr(Oid foid, Oid input_collation, Expr *node,
                                                           funcrettype,
                                                           -1,
                                                           0);
+                       TupleDescFinalize(tupdesc);
                        sexpr->funcResultDesc = tupdesc;
                        sexpr->funcReturnsTuple = false;
                }
index 7effe954286e5ff755b7f5a2c73a9e0764a953c1..07b248aa5f330ff0b45a7eb3ec88baabd4cb4242 100644 (file)
@@ -2175,6 +2175,8 @@ ExecTypeFromTLInternal(List *targetList, bool skipjunk)
                cur_resno++;
        }
 
+       TupleDescFinalize(typeInfo);
+
        return typeInfo;
 }
 
@@ -2209,6 +2211,8 @@ ExecTypeFromExprList(List *exprList)
                cur_resno++;
        }
 
+       TupleDescFinalize(typeInfo);
+
        return typeInfo;
 }
 
index 63e605e1f81e0b402096291877bf5a57aabda55e..feb82d64967274535c53a8968645ec03ed0a97c3 100644 (file)
@@ -414,6 +414,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
                                TupleDescInitEntryCollation(tupdesc,
                                                                                        (AttrNumber) 1,
                                                                                        exprCollation(funcexpr));
+                               TupleDescFinalize(tupdesc);
                        }
                        else
                        {
@@ -485,6 +486,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
                                                           0);
                }
 
+               TupleDescFinalize(scan_tupdesc);
                Assert(attno == natts);
        }
 
index e003db520de70a4c8549a8b11eebc2b73ad13927..9c415e166eef7f65101c7202d6a953e1c02c1f5d 100644 (file)
@@ -1883,6 +1883,7 @@ addRangeTableEntryForFunction(ParseState *pstate,
                        TupleDescInitEntryCollation(tupdesc,
                                                                                (AttrNumber) 1,
                                                                                exprCollation(funcexpr));
+                       TupleDescFinalize(tupdesc);
                }
                else if (functypclass == TYPEFUNC_RECORD)
                {
@@ -1940,6 +1941,7 @@ addRangeTableEntryForFunction(ParseState *pstate,
 
                                i++;
                        }
+                       TupleDescFinalize(tupdesc);
 
                        /*
                         * Ensure that the coldeflist defines a legal set of names (no
@@ -2008,7 +2010,7 @@ addRangeTableEntryForFunction(ParseState *pstate,
                                                           0);
                        /* no need to set collation */
                }
-
+               TupleDescFinalize(tupdesc);
                Assert(natts == totalatts);
        }
        else
index 3bcfc1f5e3db5357bb6e818308a79d651339fcfe..f57c4d4108054a7695470066d8efb6b525b93e94 100644 (file)
@@ -1572,6 +1572,8 @@ expandRecordVariable(ParseState *pstate, Var *var, int levelsup)
                }
                Assert(lname == NULL && lvar == NULL);  /* lists same length? */
 
+               TupleDescFinalize(tupleDesc);
+
                return tupleDesc;
        }
 
index 7c8639b32e9e6e57b2964d355c3f72c0653b0870..9f04c9ed25da615bc37279bac9ac4956270d49b4 100644 (file)
@@ -1073,6 +1073,7 @@ libpqrcv_processTuples(PGresult *pgres, WalRcvExecResult *walres,
        for (coln = 0; coln < nRetTypes; coln++)
                TupleDescInitEntry(walres->tupledesc, (AttrNumber) coln + 1,
                                                   PQfname(pgres, coln), retTypes[coln], -1, 0);
+       TupleDescFinalize(walres->tupledesc);
        attinmeta = TupleDescGetAttInMetadata(walres->tupledesc);
 
        /* No point in doing more here if there were no tuples returned. */
index 79fc192b171afd1c3409f5c8285201759a1950df..376ff46340d68ff996f6a79b88f983030a58b045 100644 (file)
@@ -452,6 +452,7 @@ IdentifySystem(void)
                                                          TEXTOID, -1, 0);
        TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 4, "dbname",
                                                          TEXTOID, -1, 0);
+       TupleDescFinalize(tupdesc);
 
        /* prepare for projection of tuples */
        tstate = begin_tup_output_tupdesc(dest, tupdesc, &TTSOpsVirtual);
@@ -497,6 +498,7 @@ ReadReplicationSlot(ReadReplicationSlotCmd *cmd)
        /* TimeLineID is unsigned, so int4 is not wide enough. */
        TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 3, "restart_tli",
                                                          INT8OID, -1, 0);
+       TupleDescFinalize(tupdesc);
 
        memset(nulls, true, READ_REPLICATION_SLOT_COLS * sizeof(bool));
 
@@ -599,6 +601,7 @@ SendTimeLineHistory(TimeLineHistoryCmd *cmd)
        tupdesc = CreateTemplateTupleDesc(2);
        TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 1, "filename", TEXTOID, -1, 0);
        TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 2, "content", TEXTOID, -1, 0);
+       TupleDescFinalize(tupdesc);
 
        TLHistoryFileName(histfname, cmd->timeline);
        TLHistoryFilePath(path, cmd->timeline);
@@ -1016,6 +1019,7 @@ StartReplication(StartReplicationCmd *cmd)
                                                                  INT8OID, -1, 0);
                TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 2, "next_tli_startpos",
                                                                  TEXTOID, -1, 0);
+               TupleDescFinalize(tupdesc);
 
                /* prepare for projection of tuple */
                tstate = begin_tup_output_tupdesc(dest, tupdesc, &TTSOpsVirtual);
@@ -1370,6 +1374,7 @@ CreateReplicationSlot(CreateReplicationSlotCmd *cmd)
                                                          TEXTOID, -1, 0);
        TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 4, "output_plugin",
                                                          TEXTOID, -1, 0);
+       TupleDescFinalize(tupdesc);
 
        /* prepare for projection of tuples */
        tstate = begin_tup_output_tupdesc(dest, tupdesc, &TTSOpsVirtual);
index 9e82c1fc1a17bf18d0983c0cb13ec8af9cbf7448..fc2e9f6686ace44202bcd726b5ef9c3a54c6201f 100644 (file)
@@ -1841,6 +1841,7 @@ aclexplode(PG_FUNCTION_ARGS)
                TupleDescInitEntry(tupdesc, (AttrNumber) 4, "is_grantable",
                                                   BOOLOID, -1, 0);
 
+               TupleDescFinalize(tupdesc);
                funcctx->tuple_desc = BlessTupleDesc(tupdesc);
 
                /* allocate memory for user context */
index c083608b1d524af0071e7815bffde976ad451984..bfb949401d0abb9516f53c8c5e7ace9262285e86 100644 (file)
@@ -454,6 +454,7 @@ pg_stat_file(PG_FUNCTION_ARGS)
                                           "creation", TIMESTAMPTZOID, -1, 0);
        TupleDescInitEntry(tupdesc, (AttrNumber) 6,
                                           "isdir", BOOLOID, -1, 0);
+       TupleDescFinalize(tupdesc);
        BlessTupleDesc(tupdesc);
 
        memset(isnull, false, sizeof(isnull));
index 9dadd6da6720d848af0ea63a1e07f47c392f9d0b..4481c354fd61967a39098d9587fb1f35038cecc9 100644 (file)
@@ -146,6 +146,7 @@ pg_lock_status(PG_FUNCTION_ARGS)
                TupleDescInitEntry(tupdesc, (AttrNumber) 16, "waitstart",
                                                   TIMESTAMPTZOID, -1, 0);
 
+               TupleDescFinalize(tupdesc);
                funcctx->tuple_desc = BlessTupleDesc(tupdesc);
 
                /*
index 3b6da8e36aca6483231dfcb377a97e78481f68f1..fd8b8676470dd35c71726104c320a7ad00047add 100644 (file)
@@ -233,6 +233,7 @@ ordered_set_startup(FunctionCallInfo fcinfo, bool use_tuples)
                                                                   -1,
                                                                   0);
 
+                               TupleDescFinalize(newdesc);
                                FreeTupleDesc(qstate->tupdesc);
                                qstate->tupdesc = newdesc;
                        }
index 5ac022274a7387443662d55c46ebcea14f417644..bad5642d9c902d3e77b79ab5896a399d5c8230b0 100644 (file)
@@ -770,6 +770,7 @@ pg_stat_get_backend_subxact(PG_FUNCTION_ARGS)
        TupleDescInitEntry(tupdesc, (AttrNumber) 2, "subxact_overflow",
                                           BOOLOID, -1, 0);
 
+       TupleDescFinalize(tupdesc);
        BlessTupleDesc(tupdesc);
 
        if ((local_beentry = pgstat_get_local_beentry_by_proc_number(procNumber)) != NULL)
@@ -1671,6 +1672,7 @@ pg_stat_wal_build_tuple(PgStat_WalCounters wal_counters,
        TupleDescInitEntry(tupdesc, (AttrNumber) 6, "stats_reset",
                                           TIMESTAMPTZOID, -1, 0);
 
+       TupleDescFinalize(tupdesc);
        BlessTupleDesc(tupdesc);
 
        /* Fill values and NULLs */
@@ -2098,6 +2100,7 @@ pg_stat_get_archiver(PG_FUNCTION_ARGS)
        TupleDescInitEntry(tupdesc, (AttrNumber) 7, "stats_reset",
                                           TIMESTAMPTZOID, -1, 0);
 
+       TupleDescFinalize(tupdesc);
        BlessTupleDesc(tupdesc);
 
        /* Get statistics about the archiver process */
@@ -2179,6 +2182,7 @@ pg_stat_get_replication_slot(PG_FUNCTION_ARGS)
                                           TIMESTAMPTZOID, -1, 0);
        TupleDescInitEntry(tupdesc, (AttrNumber) 13, "stats_reset",
                                           TIMESTAMPTZOID, -1, 0);
+       TupleDescFinalize(tupdesc);
        BlessTupleDesc(tupdesc);
 
        namestrcpy(&slotname, text_to_cstring(slotname_text));
@@ -2266,6 +2270,7 @@ pg_stat_get_subscription_stats(PG_FUNCTION_ARGS)
                                           INT8OID, -1, 0);
        TupleDescInitEntry(tupdesc, (AttrNumber) 13, "stats_reset",
                                           TIMESTAMPTZOID, -1, 0);
+       TupleDescFinalize(tupdesc);
        BlessTupleDesc(tupdesc);
 
        if (!subentry)
index 71c7c7d3b3cee794e83cc1b547f7fee5478dc7f7..d8dece42b9becebd271cdca2c6d5ee7ef86f660c 100644 (file)
@@ -651,6 +651,7 @@ tsvector_unnest(PG_FUNCTION_ARGS)
                                                   TEXTARRAYOID, -1, 0);
                if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
                        elog(ERROR, "return type must be a row type");
+               TupleDescFinalize(tupdesc);
                funcctx->tuple_desc = tupdesc;
 
                funcctx->user_fctx = PG_GETARG_TSVECTOR_COPY(0);
index a1c88c6b1b6956c48ad691d68ec36a23d9fdcbad..d27ac216e6dcae1cb9829671af48e441c78f6c58 100644 (file)
@@ -729,6 +729,8 @@ RelationBuildTupleDesc(Relation relation)
                pfree(constr);
                relation->rd_att->constr = NULL;
        }
+
+       TupleDescFinalize(relation->rd_att);
 }
 
 /*
@@ -1985,6 +1987,7 @@ formrdesc(const char *relationName, Oid relationReltype,
 
        /* initialize first attribute's attcacheoff, cf RelationBuildTupleDesc */
        TupleDescCompactAttr(relation->rd_att, 0)->attcacheoff = 0;
+       TupleDescFinalize(relation->rd_att);
 
        /* mark not-null status */
        if (has_not_null)
@@ -3688,6 +3691,8 @@ RelationBuildLocalRelation(const char *relname,
        for (i = 0; i < natts; i++)
                TupleDescAttr(rel->rd_att, i)->attrelid = relid;
 
+       TupleDescFinalize(rel->rd_att);
+
        rel->rd_rel->reltablespace = reltablespace;
 
        if (mapped_relation)
@@ -4443,6 +4448,7 @@ BuildHardcodedDescriptor(int natts, const FormData_pg_attribute *attrs)
 
        /* initialize first attribute's attcacheoff, cf RelationBuildTupleDesc */
        TupleDescCompactAttr(result, 0)->attcacheoff = 0;
+       TupleDescFinalize(result);
 
        /* Note: we don't bother to set up a TupleConstr entry */
 
@@ -6291,6 +6297,8 @@ load_relcache_init_file(bool shared)
                        populate_compact_attribute(rel->rd_att, i);
                }
 
+               TupleDescFinalize(rel->rd_att);
+
                /* next read the access method specific field */
                if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
                        goto read_failed;
index 8a934ea8dcae17c4e11006cca9e4a1d19da76251..516d02cfb82a3ce8c39a5393c599e880f3999178 100644 (file)
@@ -340,6 +340,8 @@ get_expr_result_type(Node *expr,
                                                                                exprCollation(col));
                        i++;
                }
+               TupleDescFinalize(tupdesc);
+
                if (resultTypeId)
                        *resultTypeId = rexpr->row_typeid;
                if (resultTupleDesc)
@@ -1044,6 +1046,7 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args,
                }
        }
 
+       TupleDescFinalize(tupdesc);
        return true;
 }
 
@@ -1853,6 +1856,8 @@ build_function_result_tupdesc_d(char prokind,
                                                   0);
        }
 
+       TupleDescFinalize(desc);
+
        return desc;
 }
 
@@ -1970,6 +1975,7 @@ TypeGetTupleDesc(Oid typeoid, List *colaliases)
                                                   typeoid,
                                                   -1,
                                                   0);
+               TupleDescFinalize(tupdesc);
        }
        else if (functypclass == TYPEFUNC_RECORD)
        {
index 8524dd3a981872807d36879e7f8c15395bd9a535..472cb5393ce6328cf4930ef5807e0a9289c8a965 100644 (file)
@@ -444,6 +444,7 @@ GetPGVariableResultDesc(const char *name)
                TupleDescInitEntry(tupdesc, (AttrNumber) 1, varname,
                                                   TEXTOID, -1, 0);
        }
+       TupleDescFinalize(tupdesc);
        return tupdesc;
 }
 
@@ -465,6 +466,7 @@ ShowGUCConfigOption(const char *name, DestReceiver *dest)
        tupdesc = CreateTemplateTupleDesc(1);
        TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 1, varname,
                                                          TEXTOID, -1, 0);
+       TupleDescFinalize(tupdesc);
 
        /* prepare for projection of tuples */
        tstate = begin_tup_output_tupdesc(dest, tupdesc, &TTSOpsVirtual);
@@ -499,6 +501,7 @@ ShowAllGUCConfig(DestReceiver *dest)
                                                          TEXTOID, -1, 0);
        TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 3, "description",
                                                          TEXTOID, -1, 0);
+       TupleDescFinalize(tupdesc);
 
        /* prepare for projection of tuples */
        tstate = begin_tup_output_tupdesc(dest, tupdesc, &TTSOpsVirtual);
@@ -934,6 +937,8 @@ show_all_settings(PG_FUNCTION_ARGS)
                TupleDescInitEntry(tupdesc, (AttrNumber) 17, "pending_restart",
                                                   BOOLOID, -1, 0);
 
+               TupleDescFinalize(tupdesc);
+
                /*
                 * Generate attribute metadata needed later to produce tuples from raw
                 * C strings
index d46cdbf7a3c71af98182aa45ff79ca9c3cb0c061..595413dbbc5596c1164b72731bb0e1933b73f118 100644 (file)
@@ -195,6 +195,7 @@ extern TupleDesc CreateTupleDescTruncatedCopy(TupleDesc tupdesc, int natts);
 
 extern TupleDesc CreateTupleDescCopyConstr(TupleDesc tupdesc);
 
+#define TupleDescFinalize(d) ((void) 0)
 #define TupleDescSize(src) \
        (offsetof(struct TupleDescData, compact_attrs) + \
         (src)->natts * sizeof(CompactAttribute) + \
index 5ecc7766757e98c6867933610e463baa6632d487..b72c963b3be512f61dd27f18f5d1e7e463f69d7a 100644 (file)
@@ -1912,6 +1912,8 @@ build_row_from_vars(PLpgSQL_variable **vars, int numvars)
                TupleDescInitEntryCollation(row->rowtupdesc, i + 1, typcoll);
        }
 
+       TupleDescFinalize(row->rowtupdesc);
+
        return row;
 }
 
index 485e08e5c194fb1490985abd09caf8db0000164d..f9e7c7172802cd55b661d995569d6187949f1ee0 100644 (file)
@@ -206,6 +206,7 @@ test_custom_stats_fixed_report(PG_FUNCTION_ARGS)
                                           INT8OID, -1, 0);
        TupleDescInitEntry(tupdesc, (AttrNumber) 2, "stats_reset",
                                           TIMESTAMPTZOID, -1, 0);
+       TupleDescFinalize(tupdesc);
        BlessTupleDesc(tupdesc);
 
        values[0] = Int64GetDatum(stats->numcalls);
index 679a5de456d86f3bc4931971276f67448260d939..48ca2a4ea700a62a8bf7a0074a97ee671b6683fd 100644 (file)
@@ -230,6 +230,7 @@ test_predtest(PG_FUNCTION_ARGS)
                                           "s_r_holds", BOOLOID, -1, 0);
        TupleDescInitEntry(tupdesc, (AttrNumber) 8,
                                           "w_r_holds", BOOLOID, -1, 0);
+       TupleDescFinalize(tupdesc);
        tupdesc = BlessTupleDesc(tupdesc);
 
        values[0] = BoolGetDatum(strong_implied_by);