|
|
|
|
@ -8,7 +8,7 @@ |
|
|
|
|
* Darko Prenosil <Darko.Prenosil@finteh.hr> |
|
|
|
|
* Shridhar Daithankar <shridhar_daithankar@persistent.co.in> |
|
|
|
|
* |
|
|
|
|
* $PostgreSQL: pgsql/contrib/dblink/dblink.c,v 1.69 2008/01/14 02:49:47 tgl Exp $ |
|
|
|
|
* $PostgreSQL: pgsql/contrib/dblink/dblink.c,v 1.69.2.1 2008/11/30 23:24:01 tgl Exp $ |
|
|
|
|
* Copyright (c) 2001-2008, PostgreSQL Global Development Group |
|
|
|
|
* ALL RIGHTS RESERVED; |
|
|
|
|
* |
|
|
|
|
@ -226,7 +226,6 @@ dblink_connect(PG_FUNCTION_ARGS) |
|
|
|
|
char *connstr = NULL; |
|
|
|
|
char *connname = NULL; |
|
|
|
|
char *msg; |
|
|
|
|
MemoryContext oldcontext; |
|
|
|
|
PGconn *conn = NULL; |
|
|
|
|
remoteConn *rconn = NULL; |
|
|
|
|
|
|
|
|
|
@ -240,13 +239,11 @@ dblink_connect(PG_FUNCTION_ARGS) |
|
|
|
|
else if (PG_NARGS() == 1) |
|
|
|
|
connstr = GET_STR(PG_GETARG_TEXT_P(0)); |
|
|
|
|
|
|
|
|
|
oldcontext = MemoryContextSwitchTo(TopMemoryContext); |
|
|
|
|
|
|
|
|
|
if (connname) |
|
|
|
|
rconn = (remoteConn *) palloc(sizeof(remoteConn)); |
|
|
|
|
conn = PQconnectdb(connstr); |
|
|
|
|
rconn = (remoteConn *) MemoryContextAlloc(TopMemoryContext, |
|
|
|
|
sizeof(remoteConn)); |
|
|
|
|
|
|
|
|
|
MemoryContextSwitchTo(oldcontext); |
|
|
|
|
conn = PQconnectdb(connstr); |
|
|
|
|
|
|
|
|
|
if (PQstatus(conn) == CONNECTION_BAD) |
|
|
|
|
{ |
|
|
|
|
@ -583,10 +580,10 @@ dblink_fetch(PG_FUNCTION_ARGS) |
|
|
|
|
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); |
|
|
|
|
if (!res || |
|
|
|
|
(PQresultStatus(res) != PGRES_COMMAND_OK && |
|
|
|
|
@ -633,9 +630,6 @@ dblink_fetch(PG_FUNCTION_ARGS) |
|
|
|
|
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 */ |
|
|
|
|
if (PQnfields(res) != tupdesc->natts) |
|
|
|
|
ereport(ERROR, |
|
|
|
|
@ -643,14 +637,25 @@ dblink_fetch(PG_FUNCTION_ARGS) |
|
|
|
|
errmsg("remote query result rowtype does not match " |
|
|
|
|
"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 (res) |
|
|
|
|
PQclear(res); |
|
|
|
|
PQclear(res); |
|
|
|
|
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 */ |
|
|
|
|
attinmeta = TupleDescGetAttInMetadata(tupdesc); |
|
|
|
|
funcctx->attinmeta = attinmeta; |
|
|
|
|
@ -841,7 +846,10 @@ dblink_record_internal(FunctionCallInfo fcinfo, bool is_async, bool do_get) |
|
|
|
|
res = PQgetResult(conn); |
|
|
|
|
/* NULL means we're all done with the async results */ |
|
|
|
|
if (!res) |
|
|
|
|
{ |
|
|
|
|
MemoryContextSwitchTo(oldcontext); |
|
|
|
|
SRF_RETURN_DONE(funcctx); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!res || |
|
|
|
|
@ -855,6 +863,7 @@ dblink_record_internal(FunctionCallInfo fcinfo, bool is_async, bool do_get) |
|
|
|
|
DBLINK_RES_ERROR_AS_NOTICE("sql error"); |
|
|
|
|
if (freeconn) |
|
|
|
|
PQfinish(conn); |
|
|
|
|
MemoryContextSwitchTo(oldcontext); |
|
|
|
|
SRF_RETURN_DONE(funcctx); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
@ -925,6 +934,7 @@ dblink_record_internal(FunctionCallInfo fcinfo, bool is_async, bool do_get) |
|
|
|
|
{ |
|
|
|
|
if (res) |
|
|
|
|
PQclear(res); |
|
|
|
|
MemoryContextSwitchTo(oldcontext); |
|
|
|
|
SRF_RETURN_DONE(funcctx); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -1296,8 +1306,11 @@ dblink_get_pkey(PG_FUNCTION_ARGS) |
|
|
|
|
funcctx->user_fctx = results; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
/* fast track when no results */ |
|
|
|
|
MemoryContextSwitchTo(oldcontext); |
|
|
|
|
SRF_RETURN_DONE(funcctx); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
MemoryContextSwitchTo(oldcontext); |
|
|
|
|
} |
|
|
|
|
|