Skip to content

Commit 76cc2fe

Browse files
committed
Fix dblink and tablefunc to not return with the wrong CurrentMemoryContext.
Per buildfarm results.
1 parent c1f3073 commit 76cc2fe

File tree

2 files changed

+37
-28
lines changed

2 files changed

+37
-28
lines changed

contrib/dblink/dblink.c

+28-16
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Darko Prenosil <[email protected]>
99
* Shridhar Daithankar <[email protected]>
1010
*
11-
* $PostgreSQL: pgsql/contrib/dblink/dblink.c,v 1.75 2008/09/22 13:55:13 tgl Exp $
11+
* $PostgreSQL: pgsql/contrib/dblink/dblink.c,v 1.76 2008/11/30 23:23:52 tgl Exp $
1212
* Copyright (c) 2001-2008, PostgreSQL Global Development Group
1313
* ALL RIGHTS RESERVED;
1414
*
@@ -213,7 +213,6 @@ dblink_connect(PG_FUNCTION_ARGS)
213213
char *connstr = NULL;
214214
char *connname = NULL;
215215
char *msg;
216-
MemoryContext oldcontext;
217216
PGconn *conn = NULL;
218217
remoteConn *rconn = NULL;
219218

@@ -227,17 +226,14 @@ dblink_connect(PG_FUNCTION_ARGS)
227226
else if (PG_NARGS() == 1)
228227
connstr = text_to_cstring(PG_GETARG_TEXT_PP(0));
229228

230-
oldcontext = MemoryContextSwitchTo(TopMemoryContext);
231-
232229
if (connname)
233-
rconn = (remoteConn *) palloc(sizeof(remoteConn));
230+
rconn = (remoteConn *) MemoryContextAlloc(TopMemoryContext,
231+
sizeof(remoteConn));
234232

235233
/* check password in connection string if not superuser */
236234
dblink_connstr_check(connstr);
237235
conn = PQconnectdb(connstr);
238236

239-
MemoryContextSwitchTo(oldcontext);
240-
241237
if (PQstatus(conn) == CONNECTION_BAD)
242238
{
243239
msg = pstrdup(PQerrorMessage(conn));
@@ -562,10 +558,10 @@ dblink_fetch(PG_FUNCTION_ARGS)
562558
funcctx = SRF_FIRSTCALL_INIT();
563559

564560
/*
565-
* switch to memory context appropriate for multiple function calls
561+
* Try to execute the query. Note that since libpq uses malloc,
562+
* the PGresult will be long-lived even though we are still in
563+
* a short-lived memory context.
566564
*/
567-
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
568-
569565
res = PQexec(conn, buf.data);
570566
if (!res ||
571567
(PQresultStatus(res) != PGRES_COMMAND_OK &&
@@ -607,24 +603,32 @@ dblink_fetch(PG_FUNCTION_ARGS)
607603
break;
608604
}
609605

610-
/* make sure we have a persistent copy of the tupdesc */
611-
tupdesc = CreateTupleDescCopy(tupdesc);
612-
613606
/* check result and tuple descriptor have the same number of columns */
614607
if (PQnfields(res) != tupdesc->natts)
615608
ereport(ERROR,
616609
(errcode(ERRCODE_DATATYPE_MISMATCH),
617610
errmsg("remote query result rowtype does not match "
618611
"the specified FROM clause rowtype")));
619612

620-
/* fast track when no results */
613+
/*
614+
* fast track when no results. We could exit earlier, but then
615+
* we'd not report error if the result tuple type is wrong.
616+
*/
621617
if (funcctx->max_calls < 1)
622618
{
623-
if (res)
624-
PQclear(res);
619+
PQclear(res);
625620
SRF_RETURN_DONE(funcctx);
626621
}
627622

623+
/*
624+
* switch to memory context appropriate for multiple function calls,
625+
* so we can make long-lived copy of tupdesc etc
626+
*/
627+
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
628+
629+
/* make sure we have a persistent copy of the tupdesc */
630+
tupdesc = CreateTupleDescCopy(tupdesc);
631+
628632
/* store needed metadata for subsequent calls */
629633
attinmeta = TupleDescGetAttInMetadata(tupdesc);
630634
funcctx->attinmeta = attinmeta;
@@ -815,7 +819,10 @@ dblink_record_internal(FunctionCallInfo fcinfo, bool is_async, bool do_get)
815819
res = PQgetResult(conn);
816820
/* NULL means we're all done with the async results */
817821
if (!res)
822+
{
823+
MemoryContextSwitchTo(oldcontext);
818824
SRF_RETURN_DONE(funcctx);
825+
}
819826
}
820827

821828
if (!res ||
@@ -825,6 +832,7 @@ dblink_record_internal(FunctionCallInfo fcinfo, bool is_async, bool do_get)
825832
dblink_res_error(conname, res, "could not execute query", fail);
826833
if (freeconn)
827834
PQfinish(conn);
835+
MemoryContextSwitchTo(oldcontext);
828836
SRF_RETURN_DONE(funcctx);
829837
}
830838

@@ -894,6 +902,7 @@ dblink_record_internal(FunctionCallInfo fcinfo, bool is_async, bool do_get)
894902
{
895903
if (res)
896904
PQclear(res);
905+
MemoryContextSwitchTo(oldcontext);
897906
SRF_RETURN_DONE(funcctx);
898907
}
899908

@@ -1261,8 +1270,11 @@ dblink_get_pkey(PG_FUNCTION_ARGS)
12611270
funcctx->user_fctx = results;
12621271
}
12631272
else
1273+
{
12641274
/* fast track when no results */
1275+
MemoryContextSwitchTo(oldcontext);
12651276
SRF_RETURN_DONE(funcctx);
1277+
}
12661278

12671279
MemoryContextSwitchTo(oldcontext);
12681280
}

contrib/tablefunc/tablefunc.c

+9-12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* $PostgreSQL: pgsql/contrib/tablefunc/tablefunc.c,v 1.55 2008/10/29 00:00:38 tgl Exp $
2+
* $PostgreSQL: pgsql/contrib/tablefunc/tablefunc.c,v 1.56 2008/11/30 23:23:52 tgl Exp $
33
*
44
*
55
* tablefunc
@@ -381,11 +381,6 @@ crosstab(PG_FUNCTION_ARGS)
381381
/* create a function context for cross-call persistence */
382382
funcctx = SRF_FIRSTCALL_INIT();
383383

384-
/*
385-
* switch to memory context appropriate for multiple function calls
386-
*/
387-
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
388-
389384
/* Connect to SPI manager */
390385
if ((ret = SPI_connect()) < 0)
391386
/* internal error */
@@ -426,9 +421,6 @@ crosstab(PG_FUNCTION_ARGS)
426421
SRF_RETURN_DONE(funcctx);
427422
}
428423

429-
/* SPI switches context on us, so reset it */
430-
MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
431-
432424
/* get a tuple descriptor for our result type */
433425
switch (get_call_result_type(fcinfo, NULL, &tupdesc))
434426
{
@@ -448,9 +440,6 @@ crosstab(PG_FUNCTION_ARGS)
448440
break;
449441
}
450442

451-
/* make sure we have a persistent copy of the tupdesc */
452-
tupdesc = CreateTupleDescCopy(tupdesc);
453-
454443
/*
455444
* Check that return tupdesc is compatible with the data we got from
456445
* SPI, at least based on number and type of attributes
@@ -461,6 +450,14 @@ crosstab(PG_FUNCTION_ARGS)
461450
errmsg("return and sql tuple descriptions are " \
462451
"incompatible")));
463452

453+
/*
454+
* switch to memory context appropriate for multiple function calls
455+
*/
456+
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
457+
458+
/* make sure we have a persistent copy of the tupdesc */
459+
tupdesc = CreateTupleDescCopy(tupdesc);
460+
464461
/*
465462
* Generate attribute metadata needed later to produce tuples from raw
466463
* C strings

0 commit comments

Comments
 (0)