Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 5b81703

Browse files
committed
Simplify SRFs using materialize mode in contrib/ modules
9e98583 introduced a helper to centralize building their needed state (tuplestore, tuple descriptors, etc.), checking for any errors. This commit updates all places of contrib/ that can be switched to use SetSingleFuncCall() as a drop-in replacement, resulting in the removal of a lot of boilerplate code in all the modules updated by this commit. Per analysis, some places remain as they are: - pg_logdir_ls() in adminpack/ uses historically TYPEFUNC_RECORD as return type, and I suspect that changing it may cause issues at run-time with some of its past versions, down to 1.0. - dblink/ uses a wrapper function doing exactly the work of SetSingleFuncCall(). Here the switch should be possible, but rather invasive so it does not seem the extra backpatch maintenance cost. - tablefunc/, similarly, uses multiple helper functions with portions of SetSingleFuncCall() spread across the code paths of this module. Author: Melanie Plageman Discussion: https://postgr.es/m/CAAKRu_bvDPJoL9mH6eYwvBpPtTGQwbDzfJbCM-OjkSZDu5yTPg@mail.gmail.com
1 parent d5ed9da commit 5b81703

File tree

8 files changed

+32
-301
lines changed

8 files changed

+32
-301
lines changed

contrib/amcheck/verify_heapam.c

Lines changed: 4 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,6 @@ static bool check_tuple_visibility(HeapCheckContext *ctx);
165165
static void report_corruption(HeapCheckContext *ctx, char *msg);
166166
static void report_toast_corruption(HeapCheckContext *ctx,
167167
ToastedAttribute *ta, char *msg);
168-
static TupleDesc verify_heapam_tupdesc(void);
169168
static FullTransactionId FullTransactionIdFromXidAndCtx(TransactionId xid,
170169
const HeapCheckContext *ctx);
171170
static void update_cached_xid_range(HeapCheckContext *ctx);
@@ -214,8 +213,6 @@ Datum
214213
verify_heapam(PG_FUNCTION_ARGS)
215214
{
216215
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
217-
MemoryContext old_context;
218-
bool random_access;
219216
HeapCheckContext ctx;
220217
Buffer vmbuffer = InvalidBuffer;
221218
Oid relid;
@@ -227,16 +224,6 @@ verify_heapam(PG_FUNCTION_ARGS)
227224
BlockNumber nblocks;
228225
const char *skip;
229226

230-
/* Check to see if caller supports us returning a tuplestore */
231-
if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
232-
ereport(ERROR,
233-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
234-
errmsg("set-valued function called in context that cannot accept a set")));
235-
if (!(rsinfo->allowedModes & SFRM_Materialize))
236-
ereport(ERROR,
237-
(errcode(ERRCODE_SYNTAX_ERROR),
238-
errmsg("materialize mode required, but it is not allowed in this context")));
239-
240227
/* Check supplied arguments */
241228
if (PG_ARGISNULL(0))
242229
ereport(ERROR,
@@ -290,15 +277,10 @@ verify_heapam(PG_FUNCTION_ARGS)
290277
*/
291278
ctx.attnum = -1;
292279

293-
/* The tupdesc and tuplestore must be created in ecxt_per_query_memory */
294-
old_context = MemoryContextSwitchTo(rsinfo->econtext->ecxt_per_query_memory);
295-
random_access = (rsinfo->allowedModes & SFRM_Materialize_Random) != 0;
296-
ctx.tupdesc = verify_heapam_tupdesc();
297-
ctx.tupstore = tuplestore_begin_heap(random_access, false, work_mem);
298-
rsinfo->returnMode = SFRM_Materialize;
299-
rsinfo->setResult = ctx.tupstore;
300-
rsinfo->setDesc = ctx.tupdesc;
301-
MemoryContextSwitchTo(old_context);
280+
/* Construct the tuplestore and tuple descriptor */
281+
SetSingleFuncCall(fcinfo, 0);
282+
ctx.tupdesc = rsinfo->setDesc;
283+
ctx.tupstore = rsinfo->setResult;
302284

303285
/* Open relation, check relkind and access method */
304286
ctx.rel = relation_open(relid, AccessShareLock);
@@ -630,26 +612,6 @@ report_toast_corruption(HeapCheckContext *ctx, ToastedAttribute *ta,
630612
ctx->is_corrupt = true;
631613
}
632614

633-
/*
634-
* Construct the TupleDesc used to report messages about corruptions found
635-
* while scanning the heap.
636-
*/
637-
static TupleDesc
638-
verify_heapam_tupdesc(void)
639-
{
640-
TupleDesc tupdesc;
641-
AttrNumber a = 0;
642-
643-
tupdesc = CreateTemplateTupleDesc(HEAPCHECK_RELATION_COLS);
644-
TupleDescInitEntry(tupdesc, ++a, "blkno", INT8OID, -1, 0);
645-
TupleDescInitEntry(tupdesc, ++a, "offnum", INT4OID, -1, 0);
646-
TupleDescInitEntry(tupdesc, ++a, "attnum", INT4OID, -1, 0);
647-
TupleDescInitEntry(tupdesc, ++a, "msg", TEXTOID, -1, 0);
648-
Assert(a == HEAPCHECK_RELATION_COLS);
649-
650-
return BlessTupleDesc(tupdesc);
651-
}
652-
653615
/*
654616
* Check for tuple header corruption.
655617
*

contrib/dblink/dblink.c

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1928,36 +1928,14 @@ dblink_get_notify(PG_FUNCTION_ARGS)
19281928
PGconn *conn;
19291929
PGnotify *notify;
19301930
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
1931-
TupleDesc tupdesc;
1932-
Tuplestorestate *tupstore;
1933-
MemoryContext per_query_ctx;
1934-
MemoryContext oldcontext;
1935-
1936-
prepTuplestoreResult(fcinfo);
19371931

19381932
dblink_init();
19391933
if (PG_NARGS() == 1)
19401934
conn = dblink_get_named_conn(text_to_cstring(PG_GETARG_TEXT_PP(0)));
19411935
else
19421936
conn = pconn->conn;
19431937

1944-
/* create the tuplestore in per-query memory */
1945-
per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
1946-
oldcontext = MemoryContextSwitchTo(per_query_ctx);
1947-
1948-
tupdesc = CreateTemplateTupleDesc(DBLINK_NOTIFY_COLS);
1949-
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "notify_name",
1950-
TEXTOID, -1, 0);
1951-
TupleDescInitEntry(tupdesc, (AttrNumber) 2, "be_pid",
1952-
INT4OID, -1, 0);
1953-
TupleDescInitEntry(tupdesc, (AttrNumber) 3, "extra",
1954-
TEXTOID, -1, 0);
1955-
1956-
tupstore = tuplestore_begin_heap(true, false, work_mem);
1957-
rsinfo->setResult = tupstore;
1958-
rsinfo->setDesc = tupdesc;
1959-
1960-
MemoryContextSwitchTo(oldcontext);
1938+
SetSingleFuncCall(fcinfo, 0);
19611939

19621940
PQconsumeInput(conn);
19631941
while ((notify = PQnotifies(conn)) != NULL)
@@ -1980,7 +1958,7 @@ dblink_get_notify(PG_FUNCTION_ARGS)
19801958
else
19811959
nulls[2] = true;
19821960

1983-
tuplestore_putvalues(tupstore, tupdesc, values, nulls);
1961+
tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
19841962

19851963
PQfreemem(notify);
19861964
PQconsumeInput(conn);

contrib/pageinspect/brinfuncs.c

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,6 @@ brin_page_items(PG_FUNCTION_ARGS)
126126
bytea *raw_page = PG_GETARG_BYTEA_P(0);
127127
Oid indexRelid = PG_GETARG_OID(1);
128128
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
129-
TupleDesc tupdesc;
130-
MemoryContext oldcontext;
131-
Tuplestorestate *tupstore;
132129
Relation indexRel;
133130
brin_column_state **columns;
134131
BrinDesc *bdesc;
@@ -143,29 +140,7 @@ brin_page_items(PG_FUNCTION_ARGS)
143140
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
144141
errmsg("must be superuser to use raw page functions")));
145142

146-
/* check to see if caller supports us returning a tuplestore */
147-
if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
148-
ereport(ERROR,
149-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
150-
errmsg("set-valued function called in context that cannot accept a set")));
151-
if (!(rsinfo->allowedModes & SFRM_Materialize))
152-
ereport(ERROR,
153-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
154-
errmsg("materialize mode required, but it is not allowed in this context")));
155-
156-
/* Build a tuple descriptor for our result type */
157-
if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
158-
elog(ERROR, "return type must be a row type");
159-
160-
/* Build tuplestore to hold the result rows */
161-
oldcontext = MemoryContextSwitchTo(rsinfo->econtext->ecxt_per_query_memory);
162-
163-
tupstore = tuplestore_begin_heap(true, false, work_mem);
164-
rsinfo->returnMode = SFRM_Materialize;
165-
rsinfo->setResult = tupstore;
166-
rsinfo->setDesc = tupdesc;
167-
168-
MemoryContextSwitchTo(oldcontext);
143+
SetSingleFuncCall(fcinfo, 0);
169144

170145
indexRel = index_open(indexRelid, AccessShareLock);
171146
bdesc = brin_build_desc(indexRel);
@@ -251,7 +226,7 @@ brin_page_items(PG_FUNCTION_ARGS)
251226
int att = attno - 1;
252227

253228
values[0] = UInt16GetDatum(offset);
254-
switch (TupleDescAttr(tupdesc, 1)->atttypid)
229+
switch (TupleDescAttr(rsinfo->setDesc, 1)->atttypid)
255230
{
256231
case INT8OID:
257232
values[1] = Int64GetDatum((int64) dtup->bt_blkno);
@@ -301,7 +276,7 @@ brin_page_items(PG_FUNCTION_ARGS)
301276
}
302277
}
303278

304-
tuplestore_putvalues(tupstore, tupdesc, values, nulls);
279+
tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
305280

306281
/*
307282
* If the item was unused, jump straight to the next one; otherwise,

contrib/pageinspect/gistfuncs.c

Lines changed: 4 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,6 @@ gist_page_items_bytea(PG_FUNCTION_ARGS)
9797
{
9898
bytea *raw_page = PG_GETARG_BYTEA_P(0);
9999
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
100-
bool randomAccess;
101-
TupleDesc tupdesc;
102-
Tuplestorestate *tupstore;
103-
MemoryContext oldcontext;
104100
Page page;
105101
OffsetNumber offset;
106102
OffsetNumber maxoff = InvalidOffsetNumber;
@@ -110,29 +106,7 @@ gist_page_items_bytea(PG_FUNCTION_ARGS)
110106
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
111107
errmsg("must be superuser to use raw page functions")));
112108

113-
/* check to see if caller supports us returning a tuplestore */
114-
if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
115-
ereport(ERROR,
116-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
117-
errmsg("set-valued function called in context that cannot accept a set")));
118-
if (!(rsinfo->allowedModes & SFRM_Materialize))
119-
ereport(ERROR,
120-
(errcode(ERRCODE_SYNTAX_ERROR),
121-
errmsg("materialize mode required, but it is not allowed in this context")));
122-
123-
/* The tupdesc and tuplestore must be created in ecxt_per_query_memory */
124-
oldcontext = MemoryContextSwitchTo(rsinfo->econtext->ecxt_per_query_memory);
125-
126-
if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
127-
elog(ERROR, "return type must be a row type");
128-
129-
randomAccess = (rsinfo->allowedModes & SFRM_Materialize_Random) != 0;
130-
tupstore = tuplestore_begin_heap(randomAccess, false, work_mem);
131-
rsinfo->returnMode = SFRM_Materialize;
132-
rsinfo->setResult = tupstore;
133-
rsinfo->setDesc = tupdesc;
134-
135-
MemoryContextSwitchTo(oldcontext);
109+
SetSingleFuncCall(fcinfo, 0);
136110

137111
page = get_page_from_raw(raw_page);
138112

@@ -173,7 +147,7 @@ gist_page_items_bytea(PG_FUNCTION_ARGS)
173147
values[3] = BoolGetDatum(ItemIdIsDead(id));
174148
values[4] = PointerGetDatum(tuple_bytea);
175149

176-
tuplestore_putvalues(tupstore, tupdesc, values, nulls);
150+
tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
177151
}
178152

179153
return (Datum) 0;
@@ -185,11 +159,7 @@ gist_page_items(PG_FUNCTION_ARGS)
185159
bytea *raw_page = PG_GETARG_BYTEA_P(0);
186160
Oid indexRelid = PG_GETARG_OID(1);
187161
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
188-
bool randomAccess;
189162
Relation indexRel;
190-
TupleDesc tupdesc;
191-
Tuplestorestate *tupstore;
192-
MemoryContext oldcontext;
193163
Page page;
194164
OffsetNumber offset;
195165
OffsetNumber maxoff = InvalidOffsetNumber;
@@ -199,29 +169,7 @@ gist_page_items(PG_FUNCTION_ARGS)
199169
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
200170
errmsg("must be superuser to use raw page functions")));
201171

202-
/* check to see if caller supports us returning a tuplestore */
203-
if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
204-
ereport(ERROR,
205-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
206-
errmsg("set-valued function called in context that cannot accept a set")));
207-
if (!(rsinfo->allowedModes & SFRM_Materialize))
208-
ereport(ERROR,
209-
(errcode(ERRCODE_SYNTAX_ERROR),
210-
errmsg("materialize mode required, but it is not allowed in this context")));
211-
212-
/* The tupdesc and tuplestore must be created in ecxt_per_query_memory */
213-
oldcontext = MemoryContextSwitchTo(rsinfo->econtext->ecxt_per_query_memory);
214-
215-
if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
216-
elog(ERROR, "return type must be a row type");
217-
218-
randomAccess = (rsinfo->allowedModes & SFRM_Materialize_Random) != 0;
219-
tupstore = tuplestore_begin_heap(randomAccess, false, work_mem);
220-
rsinfo->returnMode = SFRM_Materialize;
221-
rsinfo->setResult = tupstore;
222-
rsinfo->setDesc = tupdesc;
223-
224-
MemoryContextSwitchTo(oldcontext);
172+
SetSingleFuncCall(fcinfo, 0);
225173

226174
/* Open the relation */
227175
indexRel = index_open(indexRelid, AccessShareLock);
@@ -272,7 +220,7 @@ gist_page_items(PG_FUNCTION_ARGS)
272220
nulls[4] = true;
273221
}
274222

275-
tuplestore_putvalues(tupstore, tupdesc, values, nulls);
223+
tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
276224
}
277225

278226
relation_close(indexRel, AccessShareLock);

contrib/pg_stat_statements/pg_stat_statements.c

Lines changed: 3 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1494,10 +1494,6 @@ pg_stat_statements_internal(FunctionCallInfo fcinfo,
14941494
bool showtext)
14951495
{
14961496
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
1497-
TupleDesc tupdesc;
1498-
Tuplestorestate *tupstore;
1499-
MemoryContext per_query_ctx;
1500-
MemoryContext oldcontext;
15011497
Oid userid = GetUserId();
15021498
bool is_allowed_role = false;
15031499
char *qbuffer = NULL;
@@ -1516,30 +1512,14 @@ pg_stat_statements_internal(FunctionCallInfo fcinfo,
15161512
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
15171513
errmsg("pg_stat_statements must be loaded via shared_preload_libraries")));
15181514

1519-
/* check to see if caller supports us returning a tuplestore */
1520-
if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
1521-
ereport(ERROR,
1522-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1523-
errmsg("set-valued function called in context that cannot accept a set")));
1524-
if (!(rsinfo->allowedModes & SFRM_Materialize))
1525-
ereport(ERROR,
1526-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1527-
errmsg("materialize mode required, but it is not allowed in this context")));
1528-
1529-
/* Switch into long-lived context to construct returned data structures */
1530-
per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
1531-
oldcontext = MemoryContextSwitchTo(per_query_ctx);
1532-
1533-
/* Build a tuple descriptor for our result type */
1534-
if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1535-
elog(ERROR, "return type must be a row type");
1515+
SetSingleFuncCall(fcinfo, 0);
15361516

15371517
/*
15381518
* Check we have the expected number of output arguments. Aside from
15391519
* being a good safety check, we need a kluge here to detect API version
15401520
* 1.1, which was wedged into the code in an ill-considered way.
15411521
*/
1542-
switch (tupdesc->natts)
1522+
switch (rsinfo->setDesc->natts)
15431523
{
15441524
case PG_STAT_STATEMENTS_COLS_V1_0:
15451525
if (api_version != PGSS_V1_0)
@@ -1571,13 +1551,6 @@ pg_stat_statements_internal(FunctionCallInfo fcinfo,
15711551
elog(ERROR, "incorrect number of output arguments");
15721552
}
15731553

1574-
tupstore = tuplestore_begin_heap(true, false, work_mem);
1575-
rsinfo->returnMode = SFRM_Materialize;
1576-
rsinfo->setResult = tupstore;
1577-
rsinfo->setDesc = tupdesc;
1578-
1579-
MemoryContextSwitchTo(oldcontext);
1580-
15811554
/*
15821555
* We'd like to load the query text file (if needed) while not holding any
15831556
* lock on pgss->lock. In the worst case we'll have to do this again
@@ -1800,7 +1773,7 @@ pg_stat_statements_internal(FunctionCallInfo fcinfo,
18001773
api_version == PGSS_V1_9 ? PG_STAT_STATEMENTS_COLS_V1_9 :
18011774
-1 /* fail if you forget to update this assert */ ));
18021775

1803-
tuplestore_putvalues(tupstore, tupdesc, values, nulls);
1776+
tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
18041777
}
18051778

18061779
LWLockRelease(pgss->lock);

0 commit comments

Comments
 (0)