From 00bc3ecefc20daef125c766fa9ca1d5e5af4d250 Mon Sep 17 00:00:00 2001 From: David Rowley Date: Wed, 21 Jan 2026 15:41:37 +1300 Subject: [PATCH v12 3/6] Add empty TupleDescFinalize() function Currently does nothing, but will in a future commit. --- contrib/dblink/dblink.c | 4 ++++ contrib/pg_buffercache/pg_buffercache_pages.c | 2 ++ contrib/pg_visibility/pg_visibility.c | 2 ++ src/backend/access/brin/brin_tuple.c | 1 + src/backend/access/common/tupdesc.c | 13 +++++++++++++ src/backend/access/gin/ginutil.c | 1 + src/backend/access/gist/gistscan.c | 1 + src/backend/access/spgist/spgutils.c | 1 + src/backend/access/transam/twophase.c | 1 + src/backend/access/transam/xlogfuncs.c | 1 + src/backend/backup/basebackup_copy.c | 3 +++ src/backend/catalog/index.c | 2 ++ src/backend/catalog/pg_publication.c | 1 + src/backend/catalog/toasting.c | 6 ++++++ src/backend/commands/explain.c | 1 + src/backend/commands/functioncmds.c | 1 + src/backend/commands/sequence.c | 1 + src/backend/commands/tablecmds.c | 4 ++++ src/backend/commands/wait.c | 1 + src/backend/executor/execSRF.c | 2 ++ src/backend/executor/execTuples.c | 4 ++++ src/backend/executor/nodeFunctionscan.c | 2 ++ src/backend/parser/parse_relation.c | 4 +++- src/backend/parser/parse_target.c | 2 ++ .../replication/libpqwalreceiver/libpqwalreceiver.c | 1 + src/backend/replication/walsender.c | 5 +++++ src/backend/utils/adt/acl.c | 1 + src/backend/utils/adt/genfile.c | 1 + src/backend/utils/adt/lockfuncs.c | 1 + src/backend/utils/adt/orderedsetaggs.c | 1 + src/backend/utils/adt/pgstatfuncs.c | 5 +++++ src/backend/utils/adt/tsvector_op.c | 1 + src/backend/utils/cache/relcache.c | 8 ++++++++ src/backend/utils/fmgr/funcapi.c | 6 ++++++ src/backend/utils/misc/guc_funcs.c | 5 +++++ src/include/access/tupdesc.h | 1 + src/pl/plpgsql/src/pl_comp.c | 2 ++ .../test_custom_stats/test_custom_fixed_stats.c | 1 + src/test/modules/test_predtest/test_predtest.c | 1 + 39 files changed, 100 insertions(+), 1 deletion(-) diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c index 2498d80c8e7..4038950a6ef 100644 --- a/contrib/dblink/dblink.c +++ b/contrib/dblink/dblink.c @@ -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 diff --git a/contrib/pg_buffercache/pg_buffercache_pages.c b/contrib/pg_buffercache/pg_buffercache_pages.c index 89b86855243..a6b4fb5252b 100644 --- a/contrib/pg_buffercache/pg_buffercache_pages.c +++ b/contrib/pg_buffercache/pg_buffercache_pages.c @@ -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; diff --git a/contrib/pg_visibility/pg_visibility.c b/contrib/pg_visibility/pg_visibility.c index 9bc3a784bf7..dfab0b64cf5 100644 --- a/contrib/pg_visibility/pg_visibility.c +++ b/contrib/pg_visibility/pg_visibility.c @@ -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); } diff --git a/src/backend/access/brin/brin_tuple.c b/src/backend/access/brin/brin_tuple.c index 69c233c62eb..742ac089a28 100644 --- a/src/backend/access/brin/brin_tuple.c +++ b/src/backend/access/brin/brin_tuple.c @@ -84,6 +84,7 @@ brtuple_disk_tupdesc(BrinDesc *brdesc) MemoryContextSwitchTo(oldcxt); + TupleDescFinalize(tupdesc); brdesc->bd_disktdesc = tupdesc; } diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c index b69d10f0a45..2137385a833 100644 --- a/src/backend/access/common/tupdesc.c +++ b/src/backend/access/common/tupdesc.c @@ -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; } diff --git a/src/backend/access/gin/ginutil.c b/src/backend/access/gin/ginutil.c index ff927279cc3..fe7b984ff32 100644 --- a/src/backend/access/gin/ginutil.c +++ b/src/backend/access/gin/ginutil.c @@ -129,6 +129,7 @@ initGinState(GinState *state, Relation index) attr->attndims); TupleDescInitEntryCollation(state->tupdesc[i], (AttrNumber) 2, attr->attcollation); + TupleDescFinalize(state->tupdesc[i]); } /* diff --git a/src/backend/access/gist/gistscan.c b/src/backend/access/gist/gistscan.c index f23bc4a6757..c65f93abdae 100644 --- a/src/backend/access/gist/gistscan.c +++ b/src/backend/access/gist/gistscan.c @@ -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 */ diff --git a/src/backend/access/spgist/spgutils.c b/src/backend/access/spgist/spgutils.c index 9f5379b87ac..b246e8127db 100644 --- a/src/backend/access/spgist/spgutils.c +++ b/src/backend/access/spgist/spgutils.c @@ -340,6 +340,7 @@ getSpGistTupleDesc(Relation index, SpGistTypeDesc *keyType) TupleDescCompactAttr(outTupDesc, i)->attcacheoff = -1; populate_compact_attribute(outTupDesc, spgKeyColumn); + TupleDescFinalize(outTupDesc); } return outTupDesc; } diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 5f65fa7b80f..0281b58f40c 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -744,6 +744,7 @@ pg_prepared_xact(PG_FUNCTION_ARGS) TupleDescInitEntry(tupdesc, (AttrNumber) 5, "dbid", OIDOID, -1, 0); + TupleDescFinalize(tupdesc); funcctx->tuple_desc = BlessTupleDesc(tupdesc); /* diff --git a/src/backend/access/transam/xlogfuncs.c b/src/backend/access/transam/xlogfuncs.c index 78543055895..be4cc24f1db 100644 --- a/src/backend/access/transam/xlogfuncs.c +++ b/src/backend/access/transam/xlogfuncs.c @@ -427,6 +427,7 @@ pg_walfile_name_offset(PG_FUNCTION_ARGS) TupleDescInitEntry(resultTupleDesc, (AttrNumber) 2, "file_offset", INT4OID, -1, 0); + TupleDescFinalize(resultTupleDesc); resultTupleDesc = BlessTupleDesc(resultTupleDesc); /* diff --git a/src/backend/backup/basebackup_copy.c b/src/backend/backup/basebackup_copy.c index 07f58b39d8c..6c3453efd80 100644 --- a/src/backend/backup/basebackup_copy.c +++ b/src/backend/backup/basebackup_copy.c @@ -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); diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 43de42ce39e..75e97fb394a 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -481,6 +481,8 @@ ConstructTupleDescriptor(Relation heapRelation, populate_compact_attribute(indexTupDesc, i); } + TupleDescFinalize(indexTupDesc); + return indexTupDesc; } diff --git a/src/backend/catalog/pg_publication.c b/src/backend/catalog/pg_publication.c index aadc7c202c6..a79157c43bf 100644 --- a/src/backend/catalog/pg_publication.c +++ b/src/backend/catalog/pg_publication.c @@ -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; diff --git a/src/backend/catalog/toasting.c b/src/backend/catalog/toasting.c index c78dcea98c1..078a1cf5127 100644 --- a/src/backend/catalog/toasting.c +++ b/src/backend/catalog/toasting.c @@ -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. diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 93918a223b8..5f922c3f5c2 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -281,6 +281,7 @@ ExplainResultDesc(ExplainStmt *stmt) tupdesc = CreateTemplateTupleDesc(1); TupleDescInitEntry(tupdesc, (AttrNumber) 1, "QUERY PLAN", result_type, -1, 0); + TupleDescFinalize(tupdesc); return tupdesc; } diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index 242372b1e68..3afd762e9dc 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -2424,6 +2424,7 @@ CallStmtResultDesc(CallStmt *stmt) -1, 0); } + TupleDescFinalize(tupdesc); } return tupdesc; diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index e1b808bbb60..551667650ba 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -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); diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 85242dcc245..80922974970 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -1030,6 +1030,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 @@ -1458,6 +1460,8 @@ BuildDescForRelation(const List *columns) populate_compact_attribute(desc, attnum - 1); } + TupleDescFinalize(desc); + return desc; } diff --git a/src/backend/commands/wait.c b/src/backend/commands/wait.c index 1290df10c6f..8e920a72372 100644 --- a/src/backend/commands/wait.c +++ b/src/backend/commands/wait.c @@ -338,5 +338,6 @@ WaitStmtResultDesc(WaitStmt *stmt) tupdesc = CreateTemplateTupleDesc(1); TupleDescInitEntry(tupdesc, (AttrNumber) 1, "status", TEXTOID, -1, 0); + TupleDescFinalize(tupdesc); return tupdesc; } diff --git a/src/backend/executor/execSRF.c b/src/backend/executor/execSRF.c index a0b111dc0e4..b481e50acfb 100644 --- a/src/backend/executor/execSRF.c +++ b/src/backend/executor/execSRF.c @@ -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; } diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c index 7effe954286..07b248aa5f3 100644 --- a/src/backend/executor/execTuples.c +++ b/src/backend/executor/execTuples.c @@ -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; } diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c index 63e605e1f81..feb82d64967 100644 --- a/src/backend/executor/nodeFunctionscan.c +++ b/src/backend/executor/nodeFunctionscan.c @@ -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); } diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c index e003db520de..9c415e166ee 100644 --- a/src/backend/parser/parse_relation.c +++ b/src/backend/parser/parse_relation.c @@ -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 diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index 3bcfc1f5e3d..f57c4d41080 100644 --- a/src/backend/parser/parse_target.c +++ b/src/backend/parser/parse_target.c @@ -1572,6 +1572,8 @@ expandRecordVariable(ParseState *pstate, Var *var, int levelsup) } Assert(lname == NULL && lvar == NULL); /* lists same length? */ + TupleDescFinalize(tupleDesc); + return tupleDesc; } diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c index 7c8639b32e9..9f04c9ed25d 100644 --- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c +++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c @@ -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. */ diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index 2cde8ebc729..33a9e8d7f21 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -451,6 +451,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); @@ -496,6 +497,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)); @@ -598,6 +600,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); @@ -1015,6 +1018,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); @@ -1369,6 +1373,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); diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c index 071e3f2c49e..e210d6472be 100644 --- a/src/backend/utils/adt/acl.c +++ b/src/backend/utils/adt/acl.c @@ -1831,6 +1831,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 */ diff --git a/src/backend/utils/adt/genfile.c b/src/backend/utils/adt/genfile.c index c083608b1d5..bfb949401d0 100644 --- a/src/backend/utils/adt/genfile.c +++ b/src/backend/utils/adt/genfile.c @@ -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)); diff --git a/src/backend/utils/adt/lockfuncs.c b/src/backend/utils/adt/lockfuncs.c index 9dadd6da672..4481c354fd6 100644 --- a/src/backend/utils/adt/lockfuncs.c +++ b/src/backend/utils/adt/lockfuncs.c @@ -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); /* diff --git a/src/backend/utils/adt/orderedsetaggs.c b/src/backend/utils/adt/orderedsetaggs.c index 3b6da8e36ac..fd8b8676470 100644 --- a/src/backend/utils/adt/orderedsetaggs.c +++ b/src/backend/utils/adt/orderedsetaggs.c @@ -233,6 +233,7 @@ ordered_set_startup(FunctionCallInfo fcinfo, bool use_tuples) -1, 0); + TupleDescFinalize(newdesc); FreeTupleDesc(qstate->tupdesc); qstate->tupdesc = newdesc; } diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c index b1df96e7b0b..0b10da3b180 100644 --- a/src/backend/utils/adt/pgstatfuncs.c +++ b/src/backend/utils/adt/pgstatfuncs.c @@ -769,6 +769,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) @@ -1670,6 +1671,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 */ @@ -2097,6 +2099,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 */ @@ -2178,6 +2181,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)); @@ -2265,6 +2269,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) diff --git a/src/backend/utils/adt/tsvector_op.c b/src/backend/utils/adt/tsvector_op.c index 71c7c7d3b3c..d8dece42b9b 100644 --- a/src/backend/utils/adt/tsvector_op.c +++ b/src/backend/utils/adt/tsvector_op.c @@ -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); diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index a1c88c6b1b6..d27ac216e6d 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -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; diff --git a/src/backend/utils/fmgr/funcapi.c b/src/backend/utils/fmgr/funcapi.c index 8a934ea8dca..516d02cfb82 100644 --- a/src/backend/utils/fmgr/funcapi.c +++ b/src/backend/utils/fmgr/funcapi.c @@ -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) { diff --git a/src/backend/utils/misc/guc_funcs.c b/src/backend/utils/misc/guc_funcs.c index 8524dd3a981..472cb5393ce 100644 --- a/src/backend/utils/misc/guc_funcs.c +++ b/src/backend/utils/misc/guc_funcs.c @@ -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 diff --git a/src/include/access/tupdesc.h b/src/include/access/tupdesc.h index d46cdbf7a3c..595413dbbc5 100644 --- a/src/include/access/tupdesc.h +++ b/src/include/access/tupdesc.h @@ -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) + \ diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c index 5ecc7766757..b72c963b3be 100644 --- a/src/pl/plpgsql/src/pl_comp.c +++ b/src/pl/plpgsql/src/pl_comp.c @@ -1912,6 +1912,8 @@ build_row_from_vars(PLpgSQL_variable **vars, int numvars) TupleDescInitEntryCollation(row->rowtupdesc, i + 1, typcoll); } + TupleDescFinalize(row->rowtupdesc); + return row; } diff --git a/src/test/modules/test_custom_stats/test_custom_fixed_stats.c b/src/test/modules/test_custom_stats/test_custom_fixed_stats.c index 485e08e5c19..f9e7c717280 100644 --- a/src/test/modules/test_custom_stats/test_custom_fixed_stats.c +++ b/src/test/modules/test_custom_stats/test_custom_fixed_stats.c @@ -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); diff --git a/src/test/modules/test_predtest/test_predtest.c b/src/test/modules/test_predtest/test_predtest.c index 679a5de456d..48ca2a4ea70 100644 --- a/src/test/modules/test_predtest/test_predtest.c +++ b/src/test/modules/test_predtest/test_predtest.c @@ -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); -- 2.51.0