mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-21 08:29:39 +08:00
Fix dblink and tablefunc to not return with the wrong CurrentMemoryContext.
Per buildfarm results.
This commit is contained in:
parent
25a4f1afec
commit
eea4890c08
@ -8,7 +8,7 @@
|
|||||||
* Darko Prenosil <Darko.Prenosil@finteh.hr>
|
* Darko Prenosil <Darko.Prenosil@finteh.hr>
|
||||||
* Shridhar Daithankar <shridhar_daithankar@persistent.co.in>
|
* Shridhar Daithankar <shridhar_daithankar@persistent.co.in>
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/contrib/dblink/dblink.c,v 1.60.2.2 2008/01/03 21:28:18 tgl Exp $
|
* $PostgreSQL: pgsql/contrib/dblink/dblink.c,v 1.60.2.3 2008/11/30 23:24:08 tgl Exp $
|
||||||
* Copyright (c) 2001-2006, PostgreSQL Global Development Group
|
* Copyright (c) 2001-2006, PostgreSQL Global Development Group
|
||||||
* ALL RIGHTS RESERVED;
|
* ALL RIGHTS RESERVED;
|
||||||
*
|
*
|
||||||
@ -224,7 +224,6 @@ dblink_connect(PG_FUNCTION_ARGS)
|
|||||||
char *connstr = NULL;
|
char *connstr = NULL;
|
||||||
char *connname = NULL;
|
char *connname = NULL;
|
||||||
char *msg;
|
char *msg;
|
||||||
MemoryContext oldcontext;
|
|
||||||
PGconn *conn = NULL;
|
PGconn *conn = NULL;
|
||||||
remoteConn *rconn = NULL;
|
remoteConn *rconn = NULL;
|
||||||
|
|
||||||
@ -238,17 +237,14 @@ dblink_connect(PG_FUNCTION_ARGS)
|
|||||||
else if (PG_NARGS() == 1)
|
else if (PG_NARGS() == 1)
|
||||||
connstr = GET_STR(PG_GETARG_TEXT_P(0));
|
connstr = GET_STR(PG_GETARG_TEXT_P(0));
|
||||||
|
|
||||||
oldcontext = MemoryContextSwitchTo(TopMemoryContext);
|
|
||||||
|
|
||||||
if (connname)
|
if (connname)
|
||||||
rconn = (remoteConn *) palloc(sizeof(remoteConn));
|
rconn = (remoteConn *) MemoryContextAlloc(TopMemoryContext,
|
||||||
|
sizeof(remoteConn));
|
||||||
|
|
||||||
/* check password used if not superuser */
|
/* check password used if not superuser */
|
||||||
dblink_security_check(conn, rconn, connstr);
|
dblink_security_check(conn, rconn, connstr);
|
||||||
conn = PQconnectdb(connstr);
|
conn = PQconnectdb(connstr);
|
||||||
|
|
||||||
MemoryContextSwitchTo(oldcontext);
|
|
||||||
|
|
||||||
if (PQstatus(conn) == CONNECTION_BAD)
|
if (PQstatus(conn) == CONNECTION_BAD)
|
||||||
{
|
{
|
||||||
msg = pstrdup(PQerrorMessage(conn));
|
msg = pstrdup(PQerrorMessage(conn));
|
||||||
@ -581,10 +577,10 @@ dblink_fetch(PG_FUNCTION_ARGS)
|
|||||||
funcctx = SRF_FIRSTCALL_INIT();
|
funcctx = SRF_FIRSTCALL_INIT();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* switch to memory context appropriate for multiple function calls
|
* Try to execute the query. Note that since libpq uses malloc,
|
||||||
|
* the PGresult will be long-lived even though we are still in
|
||||||
|
* a short-lived memory context.
|
||||||
*/
|
*/
|
||||||
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
|
|
||||||
|
|
||||||
res = PQexec(conn, buf.data);
|
res = PQexec(conn, buf.data);
|
||||||
if (!res ||
|
if (!res ||
|
||||||
(PQresultStatus(res) != PGRES_COMMAND_OK &&
|
(PQresultStatus(res) != PGRES_COMMAND_OK &&
|
||||||
@ -631,9 +627,6 @@ dblink_fetch(PG_FUNCTION_ARGS)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make sure we have a persistent copy of the tupdesc */
|
|
||||||
tupdesc = CreateTupleDescCopy(tupdesc);
|
|
||||||
|
|
||||||
/* check result and tuple descriptor have the same number of columns */
|
/* check result and tuple descriptor have the same number of columns */
|
||||||
if (PQnfields(res) != tupdesc->natts)
|
if (PQnfields(res) != tupdesc->natts)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
@ -641,14 +634,25 @@ dblink_fetch(PG_FUNCTION_ARGS)
|
|||||||
errmsg("remote query result rowtype does not match "
|
errmsg("remote query result rowtype does not match "
|
||||||
"the specified FROM clause rowtype")));
|
"the specified FROM clause rowtype")));
|
||||||
|
|
||||||
/* fast track when no results */
|
/*
|
||||||
|
* fast track when no results. We could exit earlier, but then
|
||||||
|
* we'd not report error if the result tuple type is wrong.
|
||||||
|
*/
|
||||||
if (funcctx->max_calls < 1)
|
if (funcctx->max_calls < 1)
|
||||||
{
|
{
|
||||||
if (res)
|
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
SRF_RETURN_DONE(funcctx);
|
SRF_RETURN_DONE(funcctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* switch to memory context appropriate for multiple function calls,
|
||||||
|
* so we can make long-lived copy of tupdesc etc
|
||||||
|
*/
|
||||||
|
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
|
||||||
|
|
||||||
|
/* make sure we have a persistent copy of the tupdesc */
|
||||||
|
tupdesc = CreateTupleDescCopy(tupdesc);
|
||||||
|
|
||||||
/* store needed metadata for subsequent calls */
|
/* store needed metadata for subsequent calls */
|
||||||
attinmeta = TupleDescGetAttInMetadata(tupdesc);
|
attinmeta = TupleDescGetAttInMetadata(tupdesc);
|
||||||
funcctx->attinmeta = attinmeta;
|
funcctx->attinmeta = attinmeta;
|
||||||
@ -839,8 +843,11 @@ dblink_record_internal(FunctionCallInfo fcinfo, bool is_async, bool do_get)
|
|||||||
res = PQgetResult(conn);
|
res = PQgetResult(conn);
|
||||||
/* NULL means we're all done with the async results */
|
/* NULL means we're all done with the async results */
|
||||||
if (!res)
|
if (!res)
|
||||||
|
{
|
||||||
|
MemoryContextSwitchTo(oldcontext);
|
||||||
SRF_RETURN_DONE(funcctx);
|
SRF_RETURN_DONE(funcctx);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!res ||
|
if (!res ||
|
||||||
(PQresultStatus(res) != PGRES_COMMAND_OK &&
|
(PQresultStatus(res) != PGRES_COMMAND_OK &&
|
||||||
@ -853,6 +860,7 @@ dblink_record_internal(FunctionCallInfo fcinfo, bool is_async, bool do_get)
|
|||||||
DBLINK_RES_ERROR_AS_NOTICE("sql error");
|
DBLINK_RES_ERROR_AS_NOTICE("sql error");
|
||||||
if (freeconn)
|
if (freeconn)
|
||||||
PQfinish(conn);
|
PQfinish(conn);
|
||||||
|
MemoryContextSwitchTo(oldcontext);
|
||||||
SRF_RETURN_DONE(funcctx);
|
SRF_RETURN_DONE(funcctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -923,6 +931,7 @@ dblink_record_internal(FunctionCallInfo fcinfo, bool is_async, bool do_get)
|
|||||||
{
|
{
|
||||||
if (res)
|
if (res)
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
|
MemoryContextSwitchTo(oldcontext);
|
||||||
SRF_RETURN_DONE(funcctx);
|
SRF_RETURN_DONE(funcctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1294,8 +1303,11 @@ dblink_get_pkey(PG_FUNCTION_ARGS)
|
|||||||
funcctx->user_fctx = results;
|
funcctx->user_fctx = results;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
/* fast track when no results */
|
/* fast track when no results */
|
||||||
|
MemoryContextSwitchTo(oldcontext);
|
||||||
SRF_RETURN_DONE(funcctx);
|
SRF_RETURN_DONE(funcctx);
|
||||||
|
}
|
||||||
|
|
||||||
MemoryContextSwitchTo(oldcontext);
|
MemoryContextSwitchTo(oldcontext);
|
||||||
}
|
}
|
||||||
|
@ -381,11 +381,6 @@ crosstab(PG_FUNCTION_ARGS)
|
|||||||
/* create a function context for cross-call persistence */
|
/* create a function context for cross-call persistence */
|
||||||
funcctx = SRF_FIRSTCALL_INIT();
|
funcctx = SRF_FIRSTCALL_INIT();
|
||||||
|
|
||||||
/*
|
|
||||||
* switch to memory context appropriate for multiple function calls
|
|
||||||
*/
|
|
||||||
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
|
|
||||||
|
|
||||||
/* Connect to SPI manager */
|
/* Connect to SPI manager */
|
||||||
if ((ret = SPI_connect()) < 0)
|
if ((ret = SPI_connect()) < 0)
|
||||||
/* internal error */
|
/* internal error */
|
||||||
@ -426,9 +421,6 @@ crosstab(PG_FUNCTION_ARGS)
|
|||||||
SRF_RETURN_DONE(funcctx);
|
SRF_RETURN_DONE(funcctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SPI switches context on us, so reset it */
|
|
||||||
MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
|
|
||||||
|
|
||||||
/* get a tuple descriptor for our result type */
|
/* get a tuple descriptor for our result type */
|
||||||
switch (get_call_result_type(fcinfo, NULL, &tupdesc))
|
switch (get_call_result_type(fcinfo, NULL, &tupdesc))
|
||||||
{
|
{
|
||||||
@ -448,9 +440,6 @@ crosstab(PG_FUNCTION_ARGS)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make sure we have a persistent copy of the tupdesc */
|
|
||||||
tupdesc = CreateTupleDescCopy(tupdesc);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check that return tupdesc is compatible with the data we got from
|
* Check that return tupdesc is compatible with the data we got from
|
||||||
* SPI, at least based on number and type of attributes
|
* SPI, at least based on number and type of attributes
|
||||||
@ -461,6 +450,14 @@ crosstab(PG_FUNCTION_ARGS)
|
|||||||
errmsg("return and sql tuple descriptions are " \
|
errmsg("return and sql tuple descriptions are " \
|
||||||
"incompatible")));
|
"incompatible")));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* switch to memory context appropriate for multiple function calls
|
||||||
|
*/
|
||||||
|
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
|
||||||
|
|
||||||
|
/* make sure we have a persistent copy of the tupdesc */
|
||||||
|
tupdesc = CreateTupleDescCopy(tupdesc);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generate attribute metadata needed later to produce tuples from raw
|
* Generate attribute metadata needed later to produce tuples from raw
|
||||||
* C strings
|
* C strings
|
||||||
|
Loading…
Reference in New Issue
Block a user