From 22e3b558052aa209cba2a8fec192d76b5faef19e Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Wed, 21 Dec 2022 10:11:22 +0900 Subject: [PATCH] Switch some system functions to use get_call_result_type() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This shaves some code by replacing the combinations of CreateTemplateTupleDesc()/TupleDescInitEntry() hardcoding a mapping of the attributes listed in pg_proc.dat by get_call_result_type() to build the TupleDesc needed for the rows generated. get_call_result_type() is more expensive than the former style, but this removes some duplication with the lists of OUT parameters (pg_proc.dat and the attributes hardcoded in these code paths). This is applied to functions that are not considered as critical (aka that could be called repeatedly for monitoring purposes). Author: Bharath Rupireddy Reviewed-by: Robert Haas, Álvaro Herrera, Tom Lane, Michael Paquier Discussion: https://postgr.es/m/CALj2ACV23HW5HP5hFjd89FNS-z5X8r2jNXdMXcpN2BgTtKd87w@mail.gmail.com --- contrib/old_snapshot/time_mapping.c | 26 +----- contrib/pg_visibility/pg_visibility.c | 6 +- src/backend/access/transam/commit_ts.c | 26 +----- src/backend/access/transam/multixact.c | 9 +- src/backend/catalog/objectaddress.c | 42 ++------- src/backend/commands/sequence.c | 19 +---- src/backend/tsearch/wparser.c | 35 ++++---- src/backend/utils/adt/datetime.c | 15 +--- src/backend/utils/adt/misc.c | 31 ++----- src/backend/utils/adt/partitionfuncs.c | 14 +-- src/backend/utils/adt/tsvector_op.c | 15 ++-- src/backend/utils/misc/pg_controldata.c | 108 ++---------------------- 12 files changed, 61 insertions(+), 285 deletions(-) diff --git a/contrib/old_snapshot/time_mapping.c b/contrib/old_snapshot/time_mapping.c index 2d8cb742c34..aa4901fa1c4 100644 --- a/contrib/old_snapshot/time_mapping.c +++ b/contrib/old_snapshot/time_mapping.c @@ -38,7 +38,6 @@ PG_MODULE_MAGIC; PG_FUNCTION_INFO_V1(pg_old_snapshot_time_mapping); static OldSnapshotTimeMapping *GetOldSnapshotTimeMapping(void); -static TupleDesc MakeOldSnapshotTimeMappingTupleDesc(void); static HeapTuple MakeOldSnapshotTimeMappingTuple(TupleDesc tupdesc, OldSnapshotTimeMapping *mapping); @@ -54,12 +53,15 @@ pg_old_snapshot_time_mapping(PG_FUNCTION_ARGS) if (SRF_IS_FIRSTCALL()) { MemoryContext oldcontext; + TupleDesc tupdesc; funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); mapping = GetOldSnapshotTimeMapping(); funcctx->user_fctx = mapping; - funcctx->tuple_desc = MakeOldSnapshotTimeMappingTupleDesc(); + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); + funcctx->tuple_desc = tupdesc; MemoryContextSwitchTo(oldcontext); } @@ -101,26 +103,6 @@ GetOldSnapshotTimeMapping(void) return mapping; } -/* - * Build a tuple descriptor for the pg_old_snapshot_time_mapping() SRF. - */ -static TupleDesc -MakeOldSnapshotTimeMappingTupleDesc(void) -{ - TupleDesc tupdesc; - - tupdesc = CreateTemplateTupleDesc(NUM_TIME_MAPPING_COLUMNS); - - TupleDescInitEntry(tupdesc, (AttrNumber) 1, "array_offset", - INT4OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 2, "end_timestamp", - TIMESTAMPTZOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 3, "newest_xmin", - XIDOID, -1, 0); - - return BlessTupleDesc(tupdesc); -} - /* * Convert one entry from the old snapshot time mapping to a HeapTuple. */ diff --git a/contrib/pg_visibility/pg_visibility.c b/contrib/pg_visibility/pg_visibility.c index a95f73ec796..81f262a5f46 100644 --- a/contrib/pg_visibility/pg_visibility.c +++ b/contrib/pg_visibility/pg_visibility.c @@ -291,10 +291,8 @@ pg_visibility_map_summary(PG_FUNCTION_ARGS) ReleaseBuffer(vmbuffer); relation_close(rel, AccessShareLock); - tupdesc = CreateTemplateTupleDesc(2); - TupleDescInitEntry(tupdesc, (AttrNumber) 1, "all_visible", INT8OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 2, "all_frozen", INT8OID, -1, 0); - tupdesc = BlessTupleDesc(tupdesc); + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); values[0] = Int64GetDatum(all_visible); values[1] = Int64GetDatum(all_frozen); diff --git a/src/backend/access/transam/commit_ts.c b/src/backend/access/transam/commit_ts.c index 9aa4675cb79..5c30de57ac8 100644 --- a/src/backend/access/transam/commit_ts.c +++ b/src/backend/access/transam/commit_ts.c @@ -422,18 +422,8 @@ pg_last_committed_xact(PG_FUNCTION_ARGS) /* and construct a tuple with our data */ xid = GetLatestCommitTsData(&ts, &nodeid); - /* - * Construct a tuple descriptor for the result row. This must match this - * function's pg_proc entry! - */ - tupdesc = CreateTemplateTupleDesc(3); - TupleDescInitEntry(tupdesc, (AttrNumber) 1, "xid", - XIDOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 2, "timestamp", - TIMESTAMPTZOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 3, "roident", - OIDOID, -1, 0); - tupdesc = BlessTupleDesc(tupdesc); + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); if (!TransactionIdIsNormal(xid)) { @@ -476,16 +466,8 @@ pg_xact_commit_timestamp_origin(PG_FUNCTION_ARGS) found = TransactionIdGetCommitTsData(xid, &ts, &nodeid); - /* - * Construct a tuple descriptor for the result row. This must match this - * function's pg_proc entry! - */ - tupdesc = CreateTemplateTupleDesc(2); - TupleDescInitEntry(tupdesc, (AttrNumber) 1, "timestamp", - TIMESTAMPTZOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 2, "roident", - OIDOID, -1, 0); - tupdesc = BlessTupleDesc(tupdesc); + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); if (!found) { diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index e1191a7564c..19b95b82412 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -3373,12 +3373,9 @@ pg_get_multixact_members(PG_FUNCTION_ARGS) false); multi->iter = 0; - tupdesc = CreateTemplateTupleDesc(2); - TupleDescInitEntry(tupdesc, (AttrNumber) 1, "xid", - XIDOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 2, "mode", - TEXTOID, -1, 0); - + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); + funccxt->tuple_desc = tupdesc; funccxt->attinmeta = TupleDescGetAttInMetadata(tupdesc); funccxt->user_fctx = multi; diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c index fe97fbf79dc..109bdfb33f6 100644 --- a/src/backend/catalog/objectaddress.c +++ b/src/backend/catalog/objectaddress.c @@ -2397,14 +2397,8 @@ pg_get_object_address(PG_FUNCTION_ARGS) if (relation) relation_close(relation, AccessShareLock); - tupdesc = CreateTemplateTupleDesc(3); - TupleDescInitEntry(tupdesc, (AttrNumber) 1, "classid", - OIDOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 2, "objid", - OIDOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 3, "objsubid", - INT4OID, -1, 0); - tupdesc = BlessTupleDesc(tupdesc); + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); values[0] = ObjectIdGetDatum(addr.classId); values[1] = ObjectIdGetDatum(addr.objectId); @@ -4244,21 +4238,8 @@ pg_identify_object(PG_FUNCTION_ARGS) address.objectId = objid; address.objectSubId = objsubid; - /* - * Construct a tuple descriptor for the result row. This must match this - * function's pg_proc entry! - */ - tupdesc = CreateTemplateTupleDesc(4); - TupleDescInitEntry(tupdesc, (AttrNumber) 1, "type", - TEXTOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 2, "schema", - TEXTOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 3, "name", - TEXTOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 4, "identity", - TEXTOID, -1, 0); - - tupdesc = BlessTupleDesc(tupdesc); + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); if (is_objectclass_supported(address.classId)) { @@ -4374,19 +4355,8 @@ pg_identify_object_as_address(PG_FUNCTION_ARGS) address.objectId = objid; address.objectSubId = objsubid; - /* - * Construct a tuple descriptor for the result row. This must match this - * function's pg_proc entry! - */ - tupdesc = CreateTemplateTupleDesc(3); - TupleDescInitEntry(tupdesc, (AttrNumber) 1, "type", - TEXTOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 2, "object_names", - TEXTARRAYOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 3, "object_args", - TEXTARRAYOID, -1, 0); - - tupdesc = BlessTupleDesc(tupdesc); + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); /* object type, which can never be NULL */ values[0] = CStringGetTextDatum(getObjectTypeDescription(&address, true)); diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index 99c9f91cba5..c31c9b891a5 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -1762,23 +1762,8 @@ pg_sequence_parameters(PG_FUNCTION_ARGS) errmsg("permission denied for sequence %s", get_rel_name(relid)))); - tupdesc = CreateTemplateTupleDesc(7); - TupleDescInitEntry(tupdesc, (AttrNumber) 1, "start_value", - INT8OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 2, "minimum_value", - INT8OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 3, "maximum_value", - INT8OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 4, "increment", - INT8OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 5, "cycle_option", - BOOLOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 6, "cache_size", - INT8OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 7, "data_type", - OIDOID, -1, 0); - - BlessTupleDesc(tupdesc); + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); memset(isnull, 0, sizeof(isnull)); diff --git a/src/backend/tsearch/wparser.c b/src/backend/tsearch/wparser.c index 14bb60534f2..3ef043ac0e8 100644 --- a/src/backend/tsearch/wparser.c +++ b/src/backend/tsearch/wparser.c @@ -46,7 +46,8 @@ typedef struct HeadlineJsonState static text *headline_json_value(void *_state, char *elem_value, int elem_len); static void -tt_setup_firstcall(FuncCallContext *funcctx, Oid prsid) +tt_setup_firstcall(FuncCallContext *funcctx, FunctionCallInfo fcinfo, + Oid prsid) { TupleDesc tupdesc; MemoryContext oldcontext; @@ -66,15 +67,11 @@ tt_setup_firstcall(FuncCallContext *funcctx, Oid prsid) (Datum) 0)); funcctx->user_fctx = (void *) st; - tupdesc = CreateTemplateTupleDesc(3); - TupleDescInitEntry(tupdesc, (AttrNumber) 1, "tokid", - INT4OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 2, "alias", - TEXTOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 3, "description", - TEXTOID, -1, 0); - + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); + funcctx->tuple_desc = tupdesc; funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc); + MemoryContextSwitchTo(oldcontext); } @@ -116,7 +113,7 @@ ts_token_type_byid(PG_FUNCTION_ARGS) if (SRF_IS_FIRSTCALL()) { funcctx = SRF_FIRSTCALL_INIT(); - tt_setup_firstcall(funcctx, PG_GETARG_OID(0)); + tt_setup_firstcall(funcctx, fcinfo, PG_GETARG_OID(0)); } funcctx = SRF_PERCALL_SETUP(); @@ -139,7 +136,7 @@ ts_token_type_byname(PG_FUNCTION_ARGS) funcctx = SRF_FIRSTCALL_INIT(); prsId = get_ts_parser_oid(textToQualifiedNameList(prsname), false); - tt_setup_firstcall(funcctx, prsId); + tt_setup_firstcall(funcctx, fcinfo, prsId); } funcctx = SRF_PERCALL_SETUP(); @@ -164,7 +161,8 @@ typedef struct static void -prs_setup_firstcall(FuncCallContext *funcctx, Oid prsid, text *txt) +prs_setup_firstcall(FuncCallContext *funcctx, FunctionCallInfo fcinfo, + Oid prsid, text *txt) { TupleDesc tupdesc; MemoryContext oldcontext; @@ -209,12 +207,9 @@ prs_setup_firstcall(FuncCallContext *funcctx, Oid prsid, text *txt) st->cur = 0; funcctx->user_fctx = (void *) st; - tupdesc = CreateTemplateTupleDesc(2); - TupleDescInitEntry(tupdesc, (AttrNumber) 1, "tokid", - INT4OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 2, "token", - TEXTOID, -1, 0); - + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); + funcctx->tuple_desc = tupdesc; funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc); MemoryContextSwitchTo(oldcontext); } @@ -256,7 +251,7 @@ ts_parse_byid(PG_FUNCTION_ARGS) text *txt = PG_GETARG_TEXT_PP(1); funcctx = SRF_FIRSTCALL_INIT(); - prs_setup_firstcall(funcctx, PG_GETARG_OID(0), txt); + prs_setup_firstcall(funcctx, fcinfo, PG_GETARG_OID(0), txt); PG_FREE_IF_COPY(txt, 1); } @@ -281,7 +276,7 @@ ts_parse_byname(PG_FUNCTION_ARGS) funcctx = SRF_FIRSTCALL_INIT(); prsId = get_ts_parser_oid(textToQualifiedNameList(prsname), false); - prs_setup_firstcall(funcctx, prsId, txt); + prs_setup_firstcall(funcctx, fcinfo, prsId, txt); } funcctx = SRF_PERCALL_SETUP(); diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c index b5b117a8ca7..8afda0e5d22 100644 --- a/src/backend/utils/adt/datetime.c +++ b/src/backend/utils/adt/datetime.c @@ -4983,19 +4983,10 @@ pg_timezone_abbrevs(PG_FUNCTION_ARGS) *pindex = 0; funcctx->user_fctx = (void *) pindex; - /* - * build tupdesc for result tuples. This must match this function's - * pg_proc entry! - */ - tupdesc = CreateTemplateTupleDesc(3); - TupleDescInitEntry(tupdesc, (AttrNumber) 1, "abbrev", - TEXTOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 2, "utc_offset", - INTERVALOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 3, "is_dst", - BOOLOID, -1, 0); + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); + funcctx->tuple_desc = tupdesc; - funcctx->tuple_desc = BlessTupleDesc(tupdesc); MemoryContextSwitchTo(oldcontext); } diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c index d678d286009..7808fbd4486 100644 --- a/src/backend/utils/adt/misc.c +++ b/src/backend/utils/adt/misc.c @@ -427,18 +427,9 @@ pg_get_keywords(PG_FUNCTION_ARGS) funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); - tupdesc = CreateTemplateTupleDesc(5); - TupleDescInitEntry(tupdesc, (AttrNumber) 1, "word", - TEXTOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 2, "catcode", - CHAROID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 3, "barelabel", - BOOLOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 4, "catdesc", - TEXTOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 5, "baredesc", - TEXTOID, -1, 0); - + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); + funcctx->tuple_desc = tupdesc; funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc); MemoryContextSwitchTo(oldcontext); @@ -515,20 +506,8 @@ pg_get_catalog_foreign_keys(PG_FUNCTION_ARGS) funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); - tupdesc = CreateTemplateTupleDesc(6); - TupleDescInitEntry(tupdesc, (AttrNumber) 1, "fktable", - REGCLASSOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 2, "fkcols", - TEXTARRAYOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 3, "pktable", - REGCLASSOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 4, "pkcols", - TEXTARRAYOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 5, "is_array", - BOOLOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 6, "is_opt", - BOOLOID, -1, 0); - + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); funcctx->tuple_desc = BlessTupleDesc(tupdesc); /* diff --git a/src/backend/utils/adt/partitionfuncs.c b/src/backend/utils/adt/partitionfuncs.c index 96b5ae52d27..84518630a56 100644 --- a/src/backend/utils/adt/partitionfuncs.c +++ b/src/backend/utils/adt/partitionfuncs.c @@ -88,17 +88,9 @@ pg_partition_tree(PG_FUNCTION_ARGS) */ partitions = find_all_inheritors(rootrelid, AccessShareLock, NULL); - tupdesc = CreateTemplateTupleDesc(PG_PARTITION_TREE_COLS); - TupleDescInitEntry(tupdesc, (AttrNumber) 1, "relid", - REGCLASSOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 2, "parentid", - REGCLASSOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 3, "isleaf", - BOOLOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 4, "level", - INT4OID, -1, 0); - - funcctx->tuple_desc = BlessTupleDesc(tupdesc); + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); + funcctx->tuple_desc = tupdesc; /* The only state we need is the partition list */ funcctx->user_fctx = (void *) partitions; diff --git a/src/backend/utils/adt/tsvector_op.c b/src/backend/utils/adt/tsvector_op.c index f7c1e3d6d65..caeb85b4ca1 100644 --- a/src/backend/utils/adt/tsvector_op.c +++ b/src/backend/utils/adt/tsvector_op.c @@ -647,7 +647,9 @@ tsvector_unnest(PG_FUNCTION_ARGS) INT2ARRAYOID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 3, "weights", TEXTARRAYOID, -1, 0); - funcctx->tuple_desc = BlessTupleDesc(tupdesc); + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); + funcctx->tuple_desc = tupdesc; funcctx->user_fctx = PG_GETARG_TSVECTOR_COPY(0); @@ -2302,14 +2304,9 @@ ts_setup_firstcall(FunctionCallInfo fcinfo, FuncCallContext *funcctx, } Assert(stat->stackpos <= stat->maxdepth); - tupdesc = CreateTemplateTupleDesc(3); - TupleDescInitEntry(tupdesc, (AttrNumber) 1, "word", - TEXTOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 2, "ndoc", - INT4OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 3, "nentry", - INT4OID, -1, 0); - funcctx->tuple_desc = BlessTupleDesc(tupdesc); + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); + funcctx->tuple_desc = tupdesc; funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc); MemoryContextSwitchTo(oldcontext); diff --git a/src/backend/utils/misc/pg_controldata.c b/src/backend/utils/misc/pg_controldata.c index 781f8b87580..0703892ed4a 100644 --- a/src/backend/utils/misc/pg_controldata.c +++ b/src/backend/utils/misc/pg_controldata.c @@ -38,20 +38,8 @@ pg_control_system(PG_FUNCTION_ARGS) ControlFileData *ControlFile; bool crc_ok; - /* - * Construct a tuple descriptor for the result row. This must match this - * function's pg_proc entry! - */ - tupdesc = CreateTemplateTupleDesc(4); - TupleDescInitEntry(tupdesc, (AttrNumber) 1, "pg_control_version", - INT4OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 2, "catalog_version_no", - INT4OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 3, "system_identifier", - INT8OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 4, "pg_control_last_modified", - TIMESTAMPTZOID, -1, 0); - tupdesc = BlessTupleDesc(tupdesc); + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); /* read the control file */ ControlFile = get_controlfile(DataDir, &crc_ok); @@ -88,48 +76,8 @@ pg_control_checkpoint(PG_FUNCTION_ARGS) char xlogfilename[MAXFNAMELEN]; bool crc_ok; - /* - * Construct a tuple descriptor for the result row. This must match this - * function's pg_proc entry! - */ - tupdesc = CreateTemplateTupleDesc(18); - TupleDescInitEntry(tupdesc, (AttrNumber) 1, "checkpoint_lsn", - PG_LSNOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 2, "redo_lsn", - PG_LSNOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 3, "redo_wal_file", - TEXTOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 4, "timeline_id", - INT4OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 5, "prev_timeline_id", - INT4OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 6, "full_page_writes", - BOOLOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 7, "next_xid", - TEXTOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 8, "next_oid", - OIDOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 9, "next_multixact_id", - XIDOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 10, "next_multi_offset", - XIDOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 11, "oldest_xid", - XIDOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 12, "oldest_xid_dbid", - OIDOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 13, "oldest_active_xid", - XIDOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 14, "oldest_multi_xid", - XIDOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 15, "oldest_multi_dbid", - OIDOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 16, "oldest_commit_ts_xid", - XIDOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 17, "newest_commit_ts_xid", - XIDOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 18, "checkpoint_time", - TIMESTAMPTZOID, -1, 0); - tupdesc = BlessTupleDesc(tupdesc); + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); /* Read the control file. */ ControlFile = get_controlfile(DataDir, &crc_ok); @@ -217,22 +165,8 @@ pg_control_recovery(PG_FUNCTION_ARGS) ControlFileData *ControlFile; bool crc_ok; - /* - * Construct a tuple descriptor for the result row. This must match this - * function's pg_proc entry! - */ - tupdesc = CreateTemplateTupleDesc(5); - TupleDescInitEntry(tupdesc, (AttrNumber) 1, "min_recovery_end_lsn", - PG_LSNOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 2, "min_recovery_end_timeline", - INT4OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 3, "backup_start_lsn", - PG_LSNOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 4, "backup_end_lsn", - PG_LSNOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 5, "end_of_backup_record_required", - BOOLOID, -1, 0); - tupdesc = BlessTupleDesc(tupdesc); + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); /* read the control file */ ControlFile = get_controlfile(DataDir, &crc_ok); @@ -270,34 +204,8 @@ pg_control_init(PG_FUNCTION_ARGS) ControlFileData *ControlFile; bool crc_ok; - /* - * Construct a tuple descriptor for the result row. This must match this - * function's pg_proc entry! - */ - tupdesc = CreateTemplateTupleDesc(11); - TupleDescInitEntry(tupdesc, (AttrNumber) 1, "max_data_alignment", - INT4OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 2, "database_block_size", - INT4OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 3, "blocks_per_segment", - INT4OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 4, "wal_block_size", - INT4OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 5, "bytes_per_wal_segment", - INT4OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 6, "max_identifier_length", - INT4OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 7, "max_index_columns", - INT4OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 8, "max_toast_chunk_size", - INT4OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 9, "large_object_chunk_size", - INT4OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 10, "float8_pass_by_value", - BOOLOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 11, "data_page_checksum_version", - INT4OID, -1, 0); - tupdesc = BlessTupleDesc(tupdesc); + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); /* read the control file */ ControlFile = get_controlfile(DataDir, &crc_ok);