Added new versions of dblink, dblink_exec, dblink_open, dblink_close,
and, dblink_fetch -- allows ERROR on remote side of connection to throw NOTICE locally instead of ERROR. Also removed documentation for previously deprecated, now removed, functions.
This commit is contained in:
parent
cb659ecb40
commit
6a1e2b3c28
@ -30,13 +30,11 @@
|
||||
*
|
||||
*/
|
||||
|
||||
Version 0.6 (14 June, 2003):
|
||||
Completely removed previously deprecated functions. Added ability
|
||||
to create "named" persistent connections in addition to the single global
|
||||
"unnamed" persistent connection.
|
||||
Tested under Linux (Red Hat 9) and PostgreSQL 7.4devel.
|
||||
|
||||
Release Notes:
|
||||
Version 0.7 (as of 25 Feb, 2004)
|
||||
- Added new version of dblink, dblink_exec, dblink_open, dblink_close,
|
||||
and, dblink_fetch -- allows ERROR on remote side of connection to
|
||||
throw NOTICE locally instead of ERROR
|
||||
Version 0.6
|
||||
- functions deprecated in 0.5 have been removed
|
||||
- added ability to create "named" persistent connections
|
||||
@ -85,7 +83,7 @@ Installation:
|
||||
|
||||
You can use dblink.sql to create the functions in your database of choice, e.g.
|
||||
|
||||
psql -U postgres template1 < dblink.sql
|
||||
psql template1 < dblink.sql
|
||||
|
||||
installs following functions into database template1:
|
||||
|
||||
@ -104,40 +102,40 @@ Installation:
|
||||
|
||||
cursor
|
||||
------------
|
||||
dblink_open(text,text) RETURNS text
|
||||
dblink_open(text,text [, bool fail_on_error]) RETURNS text
|
||||
- opens a cursor using unnamed connection already opened with
|
||||
dblink_connect() that will persist for duration of current backend
|
||||
or until it is closed
|
||||
dblink_open(text,text,text) RETURNS text
|
||||
dblink_open(text,text,text [, bool fail_on_error]) RETURNS text
|
||||
- opens a cursor using a named connection already opened with
|
||||
dblink_connect() that will persist for duration of current backend
|
||||
or until it is closed
|
||||
dblink_fetch(text, int) RETURNS setof record
|
||||
dblink_fetch(text, int [, bool fail_on_error]) RETURNS setof record
|
||||
- fetches data from an already opened cursor on the unnamed connection
|
||||
dblink_fetch(text, text, int) RETURNS setof record
|
||||
dblink_fetch(text, text, int [, bool fail_on_error]) RETURNS setof record
|
||||
- fetches data from an already opened cursor on a named connection
|
||||
dblink_close(text) RETURNS text
|
||||
dblink_close(text [, bool fail_on_error]) RETURNS text
|
||||
- closes a cursor on the unnamed connection
|
||||
dblink_close(text,text) RETURNS text
|
||||
dblink_close(text,text [, bool fail_on_error]) RETURNS text
|
||||
- closes a cursor on a named connection
|
||||
|
||||
query
|
||||
------------
|
||||
dblink(text,text) RETURNS setof record
|
||||
dblink(text,text [, bool fail_on_error]) RETURNS setof record
|
||||
- returns a set of results from remote SELECT query; the first argument
|
||||
is either a connection string, or the name of an already opened
|
||||
persistant connection
|
||||
dblink(text) RETURNS setof record
|
||||
dblink(text [, bool fail_on_error]) RETURNS setof record
|
||||
- returns a set of results from remote SELECT query, using the unnamed
|
||||
connection already opened with dblink_connect()
|
||||
|
||||
execute
|
||||
------------
|
||||
dblink_exec(text, text) RETURNS text
|
||||
dblink_exec(text, text [, bool fail_on_error]) RETURNS text
|
||||
- executes an INSERT/UPDATE/DELETE query remotely; the first argument
|
||||
is either a connection string, or the name of an already opened
|
||||
persistant connection
|
||||
dblink_exec(text) RETURNS text
|
||||
dblink_exec(text [, bool fail_on_error]) RETURNS text
|
||||
- executes an INSERT/UPDATE/DELETE query remotely, using connection
|
||||
already opened with dblink_connect()
|
||||
|
||||
@ -169,7 +167,6 @@ Documentation:
|
||||
doc/query
|
||||
doc/execute
|
||||
doc/misc
|
||||
doc/deprecated
|
||||
|
||||
==================================================================
|
||||
-- Joe Conway
|
||||
|
@ -134,6 +134,16 @@ typedef struct remoteConnHashEnt
|
||||
errmsg("%s", p2), \
|
||||
errdetail("%s", msg))); \
|
||||
} while (0)
|
||||
#define DBLINK_RES_ERROR_AS_NOTICE(p2) \
|
||||
do { \
|
||||
msg = pstrdup(PQerrorMessage(conn)); \
|
||||
if (res) \
|
||||
PQclear(res); \
|
||||
ereport(NOTICE, \
|
||||
(errcode(ERRCODE_SYNTAX_ERROR), \
|
||||
errmsg("%s", p2), \
|
||||
errdetail("%s", msg))); \
|
||||
} while (0)
|
||||
#define DBLINK_CONN_NOT_AVAIL \
|
||||
do { \
|
||||
if(conname) \
|
||||
@ -152,7 +162,6 @@ typedef struct remoteConnHashEnt
|
||||
if(rcon) \
|
||||
{ \
|
||||
conn = rcon->con; \
|
||||
freeconn = false; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
@ -167,6 +176,7 @@ typedef struct remoteConnHashEnt
|
||||
errmsg("could not establish connection"), \
|
||||
errdetail("%s", msg))); \
|
||||
} \
|
||||
freeconn = true; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
@ -276,18 +286,42 @@ dblink_open(PG_FUNCTION_ARGS)
|
||||
char *conname = NULL;
|
||||
StringInfo str = makeStringInfo();
|
||||
remoteConn *rcon = NULL;
|
||||
bool fail = true; /* default to backward compatible behavior */
|
||||
|
||||
if (PG_NARGS() == 2)
|
||||
{
|
||||
/* text,text */
|
||||
curname = GET_STR(PG_GETARG_TEXT_P(0));
|
||||
sql = GET_STR(PG_GETARG_TEXT_P(1));
|
||||
conn = persistent_conn;
|
||||
}
|
||||
else if (PG_NARGS() == 3)
|
||||
{
|
||||
/* might be text,text,text or text,text,bool */
|
||||
if (get_fn_expr_argtype(fcinfo->flinfo, 2) == BOOLOID)
|
||||
{
|
||||
curname = GET_STR(PG_GETARG_TEXT_P(0));
|
||||
sql = GET_STR(PG_GETARG_TEXT_P(1));
|
||||
fail = PG_GETARG_BOOL(2);
|
||||
conn = persistent_conn;
|
||||
}
|
||||
else
|
||||
{
|
||||
conname = GET_STR(PG_GETARG_TEXT_P(0));
|
||||
curname = GET_STR(PG_GETARG_TEXT_P(1));
|
||||
sql = GET_STR(PG_GETARG_TEXT_P(2));
|
||||
}
|
||||
rcon = getConnectionByName(conname);
|
||||
if (rcon)
|
||||
conn = rcon->con;
|
||||
}
|
||||
else if (PG_NARGS() == 4)
|
||||
{
|
||||
/* text,text,text,bool */
|
||||
conname = GET_STR(PG_GETARG_TEXT_P(0));
|
||||
curname = GET_STR(PG_GETARG_TEXT_P(1));
|
||||
sql = GET_STR(PG_GETARG_TEXT_P(2));
|
||||
fail = PG_GETARG_BOOL(3);
|
||||
rcon = getConnectionByName(conname);
|
||||
if (rcon)
|
||||
conn = rcon->con;
|
||||
@ -304,13 +338,19 @@ dblink_open(PG_FUNCTION_ARGS)
|
||||
|
||||
appendStringInfo(str, "DECLARE %s CURSOR FOR %s", curname, sql);
|
||||
res = PQexec(conn, str->data);
|
||||
if (!res ||
|
||||
(PQresultStatus(res) != PGRES_COMMAND_OK &&
|
||||
PQresultStatus(res) != PGRES_TUPLES_OK))
|
||||
DBLINK_RES_ERROR("sql error");
|
||||
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
|
||||
{
|
||||
if (fail)
|
||||
DBLINK_RES_ERROR("sql error");
|
||||
else
|
||||
{
|
||||
DBLINK_RES_ERROR_AS_NOTICE("sql error");
|
||||
PQclear(res);
|
||||
PG_RETURN_TEXT_P(GET_TEXT("ERROR"));
|
||||
}
|
||||
}
|
||||
|
||||
PQclear(res);
|
||||
|
||||
PG_RETURN_TEXT_P(GET_TEXT("OK"));
|
||||
}
|
||||
|
||||
@ -328,16 +368,38 @@ dblink_close(PG_FUNCTION_ARGS)
|
||||
StringInfo str = makeStringInfo();
|
||||
char *msg;
|
||||
remoteConn *rcon = NULL;
|
||||
bool fail = true; /* default to backward compatible behavior */
|
||||
|
||||
if (PG_NARGS() == 1)
|
||||
{
|
||||
/* text */
|
||||
curname = GET_STR(PG_GETARG_TEXT_P(0));
|
||||
conn = persistent_conn;
|
||||
}
|
||||
else if (PG_NARGS() == 2)
|
||||
{
|
||||
/* might be text,text or text,bool */
|
||||
if (get_fn_expr_argtype(fcinfo->flinfo, 1) == BOOLOID)
|
||||
{
|
||||
curname = GET_STR(PG_GETARG_TEXT_P(0));
|
||||
fail = PG_GETARG_BOOL(1);
|
||||
conn = persistent_conn;
|
||||
}
|
||||
else
|
||||
{
|
||||
conname = GET_STR(PG_GETARG_TEXT_P(0));
|
||||
curname = GET_STR(PG_GETARG_TEXT_P(1));
|
||||
rcon = getConnectionByName(conname);
|
||||
if (rcon)
|
||||
conn = rcon->con;
|
||||
}
|
||||
}
|
||||
if (PG_NARGS() == 3)
|
||||
{
|
||||
/* text,text,bool */
|
||||
conname = GET_STR(PG_GETARG_TEXT_P(0));
|
||||
curname = GET_STR(PG_GETARG_TEXT_P(1));
|
||||
fail = PG_GETARG_BOOL(2);
|
||||
rcon = getConnectionByName(conname);
|
||||
if (rcon)
|
||||
conn = rcon->con;
|
||||
@ -351,7 +413,16 @@ dblink_close(PG_FUNCTION_ARGS)
|
||||
/* close the cursor */
|
||||
res = PQexec(conn, str->data);
|
||||
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
|
||||
DBLINK_RES_ERROR("sql error");
|
||||
{
|
||||
if (fail)
|
||||
DBLINK_RES_ERROR("sql error");
|
||||
else
|
||||
{
|
||||
DBLINK_RES_ERROR_AS_NOTICE("sql error");
|
||||
PQclear(res);
|
||||
PG_RETURN_TEXT_P(GET_TEXT("ERROR"));
|
||||
}
|
||||
}
|
||||
|
||||
PQclear(res);
|
||||
|
||||
@ -395,19 +466,44 @@ dblink_fetch(PG_FUNCTION_ARGS)
|
||||
char *curname = NULL;
|
||||
int howmany = 0;
|
||||
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
|
||||
bool fail = true; /* default to backward compatible */
|
||||
|
||||
if (PG_NARGS() == 3)
|
||||
if (PG_NARGS() == 4)
|
||||
{
|
||||
/* text,text,int,bool */
|
||||
conname = GET_STR(PG_GETARG_TEXT_P(0));
|
||||
curname = GET_STR(PG_GETARG_TEXT_P(1));
|
||||
howmany = PG_GETARG_INT32(2);
|
||||
fail = PG_GETARG_BOOL(3);
|
||||
|
||||
rcon = getConnectionByName(conname);
|
||||
if (rcon)
|
||||
conn = rcon->con;
|
||||
}
|
||||
else if (PG_NARGS() == 3)
|
||||
{
|
||||
/* text,text,int or text,int,bool */
|
||||
if (get_fn_expr_argtype(fcinfo->flinfo, 2) == BOOLOID)
|
||||
{
|
||||
curname = GET_STR(PG_GETARG_TEXT_P(0));
|
||||
howmany = PG_GETARG_INT32(1);
|
||||
fail = PG_GETARG_BOOL(2);
|
||||
conn = persistent_conn;
|
||||
}
|
||||
else
|
||||
{
|
||||
conname = GET_STR(PG_GETARG_TEXT_P(0));
|
||||
curname = GET_STR(PG_GETARG_TEXT_P(1));
|
||||
howmany = PG_GETARG_INT32(2);
|
||||
|
||||
rcon = getConnectionByName(conname);
|
||||
if (rcon)
|
||||
conn = rcon->con;
|
||||
}
|
||||
}
|
||||
else if (PG_NARGS() == 2)
|
||||
{
|
||||
/* text,int */
|
||||
curname = GET_STR(PG_GETARG_TEXT_P(0));
|
||||
howmany = PG_GETARG_INT32(1);
|
||||
conn = persistent_conn;
|
||||
@ -431,7 +527,17 @@ dblink_fetch(PG_FUNCTION_ARGS)
|
||||
if (!res ||
|
||||
(PQresultStatus(res) != PGRES_COMMAND_OK &&
|
||||
PQresultStatus(res) != PGRES_TUPLES_OK))
|
||||
DBLINK_RES_ERROR("sql error");
|
||||
{
|
||||
if (fail)
|
||||
DBLINK_RES_ERROR("sql error");
|
||||
else
|
||||
{
|
||||
if (res)
|
||||
PQclear(res);
|
||||
DBLINK_RES_ERROR_AS_NOTICE("sql error");
|
||||
SRF_RETURN_DONE(funcctx);
|
||||
}
|
||||
}
|
||||
else if (PQresultStatus(res) == PGRES_COMMAND_OK)
|
||||
{
|
||||
/* cursor does not exist - closed already or bad name */
|
||||
@ -448,7 +554,11 @@ dblink_fetch(PG_FUNCTION_ARGS)
|
||||
|
||||
/* fast track when no results */
|
||||
if (funcctx->max_calls < 1)
|
||||
{
|
||||
if (res)
|
||||
PQclear(res);
|
||||
SRF_RETURN_DONE(funcctx);
|
||||
}
|
||||
|
||||
/* check typtype to see if we have a predetermined return type */
|
||||
functypeid = get_func_rettype(funcid);
|
||||
@ -546,7 +656,7 @@ dblink_record(PG_FUNCTION_ARGS)
|
||||
bool is_sql_cmd = false;
|
||||
char *sql_cmd_status = NULL;
|
||||
MemoryContext oldcontext;
|
||||
bool freeconn = true;
|
||||
bool freeconn = false;
|
||||
|
||||
/* stuff done only on the first call of the function */
|
||||
if (SRF_IS_FIRSTCALL())
|
||||
@ -560,6 +670,7 @@ dblink_record(PG_FUNCTION_ARGS)
|
||||
char *conname = NULL;
|
||||
remoteConn *rcon = NULL;
|
||||
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
|
||||
bool fail = true; /* default to backward compatible */
|
||||
|
||||
/* create a function context for cross-call persistence */
|
||||
funcctx = SRF_FIRSTCALL_INIT();
|
||||
@ -570,13 +681,31 @@ dblink_record(PG_FUNCTION_ARGS)
|
||||
*/
|
||||
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
|
||||
|
||||
if (PG_NARGS() == 2)
|
||||
if (PG_NARGS() == 3)
|
||||
{
|
||||
/* text,text,bool */
|
||||
DBLINK_GET_CONN;
|
||||
sql = GET_STR(PG_GETARG_TEXT_P(1));
|
||||
fail = PG_GETARG_BOOL(2);
|
||||
}
|
||||
else if (PG_NARGS() == 2)
|
||||
{
|
||||
/* text,text or text,bool */
|
||||
if (get_fn_expr_argtype(fcinfo->flinfo, 1) == BOOLOID)
|
||||
{
|
||||
conn = persistent_conn;
|
||||
sql = GET_STR(PG_GETARG_TEXT_P(0));
|
||||
fail = PG_GETARG_BOOL(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBLINK_GET_CONN;
|
||||
sql = GET_STR(PG_GETARG_TEXT_P(1));
|
||||
}
|
||||
}
|
||||
else if (PG_NARGS() == 1)
|
||||
{
|
||||
/* text */
|
||||
conn = persistent_conn;
|
||||
sql = GET_STR(PG_GETARG_TEXT_P(0));
|
||||
}
|
||||
@ -588,8 +717,22 @@ dblink_record(PG_FUNCTION_ARGS)
|
||||
DBLINK_CONN_NOT_AVAIL;
|
||||
|
||||
res = PQexec(conn, sql);
|
||||
if (!res || (PQresultStatus(res) != PGRES_COMMAND_OK && PQresultStatus(res) != PGRES_TUPLES_OK))
|
||||
DBLINK_RES_ERROR("sql error");
|
||||
if (!res ||
|
||||
(PQresultStatus(res) != PGRES_COMMAND_OK &&
|
||||
PQresultStatus(res) != PGRES_TUPLES_OK))
|
||||
{
|
||||
if (fail)
|
||||
DBLINK_RES_ERROR("sql error");
|
||||
else
|
||||
{
|
||||
if (res)
|
||||
PQclear(res);
|
||||
if (freeconn)
|
||||
PQfinish(conn);
|
||||
DBLINK_RES_ERROR_AS_NOTICE("sql error");
|
||||
SRF_RETURN_DONE(funcctx);
|
||||
}
|
||||
}
|
||||
|
||||
if (PQresultStatus(res) == PGRES_COMMAND_OK)
|
||||
{
|
||||
@ -614,12 +757,16 @@ dblink_record(PG_FUNCTION_ARGS)
|
||||
funcctx->user_fctx = res;
|
||||
|
||||
/* if needed, close the connection to the database and cleanup */
|
||||
if (freeconn && PG_NARGS() == 2)
|
||||
if (freeconn)
|
||||
PQfinish(conn);
|
||||
|
||||
/* fast track when no results */
|
||||
if (funcctx->max_calls < 1)
|
||||
{
|
||||
if (res)
|
||||
PQclear(res);
|
||||
SRF_RETURN_DONE(funcctx);
|
||||
}
|
||||
|
||||
/* check typtype to see if we have a predetermined return type */
|
||||
functypeid = get_func_rettype(funcid);
|
||||
@ -727,15 +874,34 @@ dblink_exec(PG_FUNCTION_ARGS)
|
||||
char *sql = NULL;
|
||||
char *conname = NULL;
|
||||
remoteConn *rcon = NULL;
|
||||
bool freeconn = true;
|
||||
bool freeconn = false;
|
||||
bool fail = true; /* default to backward compatible behavior */
|
||||
|
||||
if (PG_NARGS() == 2)
|
||||
if (PG_NARGS() == 3)
|
||||
{
|
||||
/* must be text,text,bool */
|
||||
DBLINK_GET_CONN;
|
||||
sql = GET_STR(PG_GETARG_TEXT_P(1));
|
||||
fail = PG_GETARG_BOOL(2);
|
||||
}
|
||||
else if (PG_NARGS() == 2)
|
||||
{
|
||||
/* might be text,text or text,bool */
|
||||
if (get_fn_expr_argtype(fcinfo->flinfo, 1) == BOOLOID)
|
||||
{
|
||||
conn = persistent_conn;
|
||||
sql = GET_STR(PG_GETARG_TEXT_P(0));
|
||||
fail = PG_GETARG_BOOL(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBLINK_GET_CONN;
|
||||
sql = GET_STR(PG_GETARG_TEXT_P(1));
|
||||
}
|
||||
}
|
||||
else if (PG_NARGS() == 1)
|
||||
{
|
||||
/* must be single text argument */
|
||||
conn = persistent_conn;
|
||||
sql = GET_STR(PG_GETARG_TEXT_P(0));
|
||||
}
|
||||
@ -750,9 +916,25 @@ dblink_exec(PG_FUNCTION_ARGS)
|
||||
if (!res ||
|
||||
(PQresultStatus(res) != PGRES_COMMAND_OK &&
|
||||
PQresultStatus(res) != PGRES_TUPLES_OK))
|
||||
DBLINK_RES_ERROR("sql error");
|
||||
{
|
||||
if (fail)
|
||||
DBLINK_RES_ERROR("sql error");
|
||||
else
|
||||
DBLINK_RES_ERROR_AS_NOTICE("sql error");
|
||||
|
||||
if (PQresultStatus(res) == PGRES_COMMAND_OK)
|
||||
/* need a tuple descriptor representing one TEXT column */
|
||||
tupdesc = CreateTemplateTupleDesc(1, false);
|
||||
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "status",
|
||||
TEXTOID, -1, 0, false);
|
||||
|
||||
/*
|
||||
* and save a copy of the command status string to return as our
|
||||
* result tuple
|
||||
*/
|
||||
sql_cmd_status = GET_TEXT("ERROR");
|
||||
|
||||
}
|
||||
else if (PQresultStatus(res) == PGRES_COMMAND_OK)
|
||||
{
|
||||
/* need a tuple descriptor representing one TEXT column */
|
||||
tupdesc = CreateTemplateTupleDesc(1, false);
|
||||
@ -773,7 +955,7 @@ dblink_exec(PG_FUNCTION_ARGS)
|
||||
PQclear(res);
|
||||
|
||||
/* if needed, close the connection to the database and cleanup */
|
||||
if (freeconn && fcinfo->nargs == 2)
|
||||
if (freeconn)
|
||||
PQfinish(conn);
|
||||
|
||||
PG_RETURN_TEXT_P(sql_cmd_status);
|
||||
|
@ -1,94 +1,144 @@
|
||||
CREATE OR REPLACE FUNCTION dblink_connect (text)
|
||||
RETURNS text
|
||||
AS 'MODULE_PATHNAME','dblink_connect'
|
||||
LANGUAGE 'C' WITH (isstrict);
|
||||
LANGUAGE 'C' STRICT;
|
||||
|
||||
CREATE OR REPLACE FUNCTION dblink_connect (text, text)
|
||||
RETURNS text
|
||||
AS 'MODULE_PATHNAME','dblink_connect'
|
||||
LANGUAGE 'C' WITH (isstrict);
|
||||
LANGUAGE 'C' STRICT;
|
||||
|
||||
CREATE OR REPLACE FUNCTION dblink_disconnect ()
|
||||
RETURNS text
|
||||
AS 'MODULE_PATHNAME','dblink_disconnect'
|
||||
LANGUAGE 'C' WITH (isstrict);
|
||||
LANGUAGE 'C' STRICT;
|
||||
|
||||
CREATE OR REPLACE FUNCTION dblink_disconnect (text)
|
||||
RETURNS text
|
||||
AS 'MODULE_PATHNAME','dblink_disconnect'
|
||||
LANGUAGE 'C' WITH (isstrict);
|
||||
LANGUAGE 'C' STRICT;
|
||||
|
||||
CREATE OR REPLACE FUNCTION dblink_open (text,text)
|
||||
RETURNS text
|
||||
AS 'MODULE_PATHNAME','dblink_open'
|
||||
LANGUAGE 'C' WITH (isstrict);
|
||||
LANGUAGE 'C' STRICT;
|
||||
|
||||
CREATE OR REPLACE FUNCTION dblink_open (text,text,bool)
|
||||
RETURNS text
|
||||
AS 'MODULE_PATHNAME','dblink_open'
|
||||
LANGUAGE 'C' STRICT;
|
||||
|
||||
CREATE OR REPLACE FUNCTION dblink_open (text,text,text)
|
||||
RETURNS text
|
||||
AS 'MODULE_PATHNAME','dblink_open'
|
||||
LANGUAGE 'C' WITH (isstrict);
|
||||
LANGUAGE 'C' STRICT;
|
||||
|
||||
CREATE OR REPLACE FUNCTION dblink_open (text,text,text,bool)
|
||||
RETURNS text
|
||||
AS 'MODULE_PATHNAME','dblink_open'
|
||||
LANGUAGE 'C' STRICT;
|
||||
|
||||
CREATE OR REPLACE FUNCTION dblink_fetch (text,int)
|
||||
RETURNS setof record
|
||||
AS 'MODULE_PATHNAME','dblink_fetch'
|
||||
LANGUAGE 'C' WITH (isstrict);
|
||||
LANGUAGE 'C' STRICT;
|
||||
|
||||
CREATE OR REPLACE FUNCTION dblink_fetch (text,int,bool)
|
||||
RETURNS setof record
|
||||
AS 'MODULE_PATHNAME','dblink_fetch'
|
||||
LANGUAGE 'C' STRICT;
|
||||
|
||||
CREATE OR REPLACE FUNCTION dblink_fetch (text,text,int)
|
||||
RETURNS setof record
|
||||
AS 'MODULE_PATHNAME','dblink_fetch'
|
||||
LANGUAGE 'C' WITH (isstrict);
|
||||
LANGUAGE 'C' STRICT;
|
||||
|
||||
CREATE OR REPLACE FUNCTION dblink_fetch (text,text,int,bool)
|
||||
RETURNS setof record
|
||||
AS 'MODULE_PATHNAME','dblink_fetch'
|
||||
LANGUAGE 'C' STRICT;
|
||||
|
||||
CREATE OR REPLACE FUNCTION dblink_close (text)
|
||||
RETURNS text
|
||||
AS 'MODULE_PATHNAME','dblink_close'
|
||||
LANGUAGE 'C' WITH (isstrict);
|
||||
LANGUAGE 'C' STRICT;
|
||||
|
||||
CREATE OR REPLACE FUNCTION dblink_close (text,bool)
|
||||
RETURNS text
|
||||
AS 'MODULE_PATHNAME','dblink_close'
|
||||
LANGUAGE 'C' STRICT;
|
||||
|
||||
CREATE OR REPLACE FUNCTION dblink_close (text,text)
|
||||
RETURNS text
|
||||
AS 'MODULE_PATHNAME','dblink_close'
|
||||
LANGUAGE 'C' WITH (isstrict);
|
||||
LANGUAGE 'C' STRICT;
|
||||
|
||||
CREATE OR REPLACE FUNCTION dblink_close (text,text,bool)
|
||||
RETURNS text
|
||||
AS 'MODULE_PATHNAME','dblink_close'
|
||||
LANGUAGE 'C' STRICT;
|
||||
|
||||
CREATE OR REPLACE FUNCTION dblink (text,text)
|
||||
RETURNS setof record
|
||||
AS 'MODULE_PATHNAME','dblink_record'
|
||||
LANGUAGE 'C' WITH (isstrict);
|
||||
LANGUAGE 'C' STRICT;
|
||||
|
||||
CREATE OR REPLACE FUNCTION dblink (text,text,bool)
|
||||
RETURNS setof record
|
||||
AS 'MODULE_PATHNAME','dblink_record'
|
||||
LANGUAGE 'C' STRICT;
|
||||
|
||||
CREATE OR REPLACE FUNCTION dblink (text)
|
||||
RETURNS setof record
|
||||
AS 'MODULE_PATHNAME','dblink_record'
|
||||
LANGUAGE 'C' WITH (isstrict);
|
||||
LANGUAGE 'C' STRICT;
|
||||
|
||||
CREATE OR REPLACE FUNCTION dblink (text,bool)
|
||||
RETURNS setof record
|
||||
AS 'MODULE_PATHNAME','dblink_record'
|
||||
LANGUAGE 'C' STRICT;
|
||||
|
||||
CREATE OR REPLACE FUNCTION dblink_exec (text,text)
|
||||
RETURNS text
|
||||
AS 'MODULE_PATHNAME','dblink_exec'
|
||||
LANGUAGE 'C' WITH (isstrict);
|
||||
LANGUAGE 'C' STRICT;
|
||||
|
||||
CREATE OR REPLACE FUNCTION dblink_exec (text,text,bool)
|
||||
RETURNS text
|
||||
AS 'MODULE_PATHNAME','dblink_exec'
|
||||
LANGUAGE 'C' STRICT;
|
||||
|
||||
CREATE OR REPLACE FUNCTION dblink_exec (text)
|
||||
RETURNS text
|
||||
AS 'MODULE_PATHNAME','dblink_exec'
|
||||
LANGUAGE 'c' WITH (isstrict);
|
||||
LANGUAGE 'c' STRICT;
|
||||
|
||||
CREATE OR REPLACE FUNCTION dblink_exec (text,bool)
|
||||
RETURNS text
|
||||
AS 'MODULE_PATHNAME','dblink_exec'
|
||||
LANGUAGE 'c' STRICT;
|
||||
|
||||
CREATE TYPE dblink_pkey_results AS (position int4, colname text);
|
||||
|
||||
CREATE OR REPLACE FUNCTION dblink_get_pkey (text)
|
||||
RETURNS setof dblink_pkey_results
|
||||
AS 'MODULE_PATHNAME','dblink_get_pkey'
|
||||
LANGUAGE 'c' WITH (isstrict);
|
||||
LANGUAGE 'c' STRICT;
|
||||
|
||||
CREATE OR REPLACE FUNCTION dblink_build_sql_insert (text, int2vector, int4, _text, _text)
|
||||
RETURNS text
|
||||
AS 'MODULE_PATHNAME','dblink_build_sql_insert'
|
||||
LANGUAGE 'C' WITH (isstrict);
|
||||
LANGUAGE 'C' STRICT;
|
||||
|
||||
CREATE OR REPLACE FUNCTION dblink_build_sql_delete (text, int2vector, int4, _text)
|
||||
RETURNS text
|
||||
AS 'MODULE_PATHNAME','dblink_build_sql_delete'
|
||||
LANGUAGE 'C' WITH (isstrict);
|
||||
LANGUAGE 'C' STRICT;
|
||||
|
||||
CREATE OR REPLACE FUNCTION dblink_build_sql_update (text, int2vector, int4, _text, _text)
|
||||
RETURNS text
|
||||
AS 'MODULE_PATHNAME','dblink_build_sql_update'
|
||||
LANGUAGE 'C' WITH (isstrict);
|
||||
LANGUAGE 'C' STRICT;
|
||||
|
||||
CREATE OR REPLACE FUNCTION dblink_current_query ()
|
||||
RETURNS text
|
||||
|
@ -5,8 +5,8 @@ dblink_open -- Opens a cursor on a remote database
|
||||
|
||||
Synopsis
|
||||
|
||||
dblink_open(text cursorname, text sql)
|
||||
dblink_open(text connname, text cursorname, text sql)
|
||||
dblink_open(text cursorname, text sql [, bool fail_on_error])
|
||||
dblink_open(text connname, text cursorname, text sql [, bool fail_on_error])
|
||||
|
||||
Inputs
|
||||
|
||||
@ -23,6 +23,13 @@ Inputs
|
||||
sql statement that you wish to execute on the remote host
|
||||
e.g. "select * from pg_class"
|
||||
|
||||
fail_on_error
|
||||
|
||||
If true (default when not present) then an ERROR thrown on the remote side
|
||||
of the connection causes an ERROR to also be thrown locally. If false, the
|
||||
remote ERROR is locally treated as a NOTICE, and the return value is set
|
||||
to 'ERROR'.
|
||||
|
||||
Outputs
|
||||
|
||||
Returns status = "OK"
|
||||
@ -56,8 +63,8 @@ dblink_fetch -- Returns a set from an open cursor on a remote database
|
||||
|
||||
Synopsis
|
||||
|
||||
dblink_fetch(text cursorname, int32 howmany)
|
||||
dblink_fetch(text connname, text cursorname, int32 howmany)
|
||||
dblink_fetch(text cursorname, int32 howmany [, bool fail_on_error])
|
||||
dblink_fetch(text connname, text cursorname, int32 howmany [, bool fail_on_error])
|
||||
|
||||
Inputs
|
||||
|
||||
@ -75,6 +82,12 @@ Inputs
|
||||
starting at the current cursor position, moving forward. Once the cursor
|
||||
has positioned to the end, no more rows are produced.
|
||||
|
||||
fail_on_error
|
||||
|
||||
If true (default when not present) then an ERROR thrown on the remote side
|
||||
of the connection causes an ERROR to also be thrown locally. If false, the
|
||||
remote ERROR is locally treated as a NOTICE, and no rows are returned.
|
||||
|
||||
Outputs
|
||||
|
||||
Returns setof record
|
||||
@ -132,8 +145,8 @@ dblink_close -- Closes a cursor on a remote database
|
||||
|
||||
Synopsis
|
||||
|
||||
dblink_close(text cursorname)
|
||||
dblink_close(text connname, text cursorname)
|
||||
dblink_close(text cursorname [, bool fail_on_error])
|
||||
dblink_close(text connname, text cursorname [, bool fail_on_error])
|
||||
|
||||
Inputs
|
||||
|
||||
@ -145,6 +158,13 @@ Inputs
|
||||
|
||||
a reference name for the cursor
|
||||
|
||||
fail_on_error
|
||||
|
||||
If true (default when not present) then an ERROR thrown on the remote side
|
||||
of the connection causes an ERROR to also be thrown locally. If false, the
|
||||
remote ERROR is locally treated as a NOTICE, and the return value is set
|
||||
to 'ERROR'.
|
||||
|
||||
Outputs
|
||||
|
||||
Returns status = "OK"
|
||||
|
@ -1,105 +0,0 @@
|
||||
==================================================================
|
||||
Name
|
||||
|
||||
*DEPRECATED* use new dblink syntax
|
||||
dblink -- Returns a resource id for a data set from a remote database
|
||||
|
||||
Synopsis
|
||||
|
||||
dblink(text connstr, text sql)
|
||||
|
||||
Inputs
|
||||
|
||||
connstr
|
||||
|
||||
standard libpq format connection srting,
|
||||
e.g. "hostaddr=127.0.0.1 port=5432 dbname=mydb user=postgres password=mypasswd"
|
||||
|
||||
sql
|
||||
|
||||
sql statement that you wish to execute on the remote host
|
||||
e.g. "select * from pg_class"
|
||||
|
||||
Outputs
|
||||
|
||||
Returns setof int (res_id)
|
||||
|
||||
Example usage
|
||||
|
||||
select dblink('hostaddr=127.0.0.1 port=5432 dbname=mydb user=postgres password=mypasswd'
|
||||
,'select f1, f2 from mytable');
|
||||
|
||||
==================================================================
|
||||
|
||||
Name
|
||||
|
||||
*DEPRECATED* use new dblink syntax
|
||||
dblink_tok -- Returns individual select field results from a dblink remote query
|
||||
|
||||
Synopsis
|
||||
|
||||
dblink_tok(int res_id, int fnumber)
|
||||
|
||||
Inputs
|
||||
|
||||
res_id
|
||||
|
||||
a resource id returned by a call to dblink()
|
||||
|
||||
fnumber
|
||||
|
||||
the ordinal position (zero based) of the field to be returned from the dblink result set
|
||||
|
||||
Outputs
|
||||
|
||||
Returns text
|
||||
|
||||
Example usage
|
||||
|
||||
select dblink_tok(t1.dblink_p,0) as f1, dblink_tok(t1.dblink_p,1) as f2
|
||||
from (select dblink('hostaddr=127.0.0.1 port=5432 dbname=mydb user=postgres password=mypasswd'
|
||||
,'select f1, f2 from mytable') as dblink_p) as t1;
|
||||
|
||||
|
||||
==================================================================
|
||||
*DEPRECATED* use new dblink syntax
|
||||
A more convenient way to use dblink may be to create a view:
|
||||
|
||||
create view myremotetable as
|
||||
select dblink_tok(t1.dblink_p,0) as f1, dblink_tok(t1.dblink_p,1) as f2
|
||||
from (select dblink('hostaddr=127.0.0.1 port=5432 dbname=template1 user=postgres password=postgres'
|
||||
,'select proname, prosrc from pg_proc') as dblink_p) as t1;
|
||||
|
||||
Then you can simply write:
|
||||
|
||||
select f1, f2 from myremotetable where f1 like 'bytea%';
|
||||
|
||||
==================================================================
|
||||
Name
|
||||
*DEPRECATED* use new dblink_exec syntax
|
||||
dblink_last_oid -- Returns last inserted oid
|
||||
|
||||
Synopsis
|
||||
|
||||
dblink_last_oid(int res_id) RETURNS oid
|
||||
|
||||
Inputs
|
||||
|
||||
res_id
|
||||
|
||||
any resource id returned by dblink function;
|
||||
|
||||
Outputs
|
||||
|
||||
Returns oid of last inserted tuple
|
||||
|
||||
Example usage
|
||||
|
||||
test=# select dblink_last_oid(dblink('hostaddr=127.0.0.1 port=5432 dbname=mydb user=postgres password=mypasswd'
|
||||
,'insert into mytable (f1, f2) values (1,2)'));
|
||||
|
||||
dblink_last_oid
|
||||
----------------
|
||||
16553
|
||||
(1 row)
|
||||
|
@ -5,14 +5,15 @@ dblink_exec -- Executes an UPDATE/INSERT/DELETE on a remote database
|
||||
|
||||
Synopsis
|
||||
|
||||
dblink_exec(text connstr, text sql)
|
||||
dblink_exec(text connname, text sql)
|
||||
dblink_exec(text sql)
|
||||
dblink_exec(text connstr, text sql [, bool fail_on_error])
|
||||
dblink_exec(text connname, text sql [, bool fail_on_error])
|
||||
dblink_exec(text sql [, bool fail_on_error])
|
||||
|
||||
Inputs
|
||||
|
||||
connname
|
||||
connstr
|
||||
|
||||
If two arguments are present, the first is first assumed to be a specific
|
||||
connection name to use. If the name is not found, the argument is then
|
||||
assumed to be a valid connection string, of standard libpq format,
|
||||
@ -25,9 +26,16 @@ Inputs
|
||||
sql statement that you wish to execute on the remote host, e.g.:
|
||||
insert into foo values(0,'a','{"a0","b0","c0"}');
|
||||
|
||||
fail_on_error
|
||||
|
||||
If true (default when not present) then an ERROR thrown on the remote side
|
||||
of the connection causes an ERROR to also be thrown locally. If false, the
|
||||
remote ERROR is locally treated as a NOTICE, and the return value is set
|
||||
to 'ERROR'.
|
||||
|
||||
Outputs
|
||||
|
||||
Returns status of the command
|
||||
Returns status of the command, or 'ERROR' if the command failed.
|
||||
|
||||
Notes
|
||||
1) dblink_open starts an explicit transaction. If, after using dblink_open,
|
||||
@ -60,3 +68,12 @@ select dblink_exec('myconn','insert into foo values(21,''z'',''{"a0","b0","c0"}'
|
||||
------------------
|
||||
INSERT 6432584 1
|
||||
(1 row)
|
||||
|
||||
select dblink_exec('myconn','insert into pg_class values (''foo'')',false);
|
||||
NOTICE: sql error
|
||||
DETAIL: ERROR: null value in column "relnamespace" violates not-null constraint
|
||||
|
||||
dblink_exec
|
||||
-------------
|
||||
ERROR
|
||||
(1 row)
|
||||
|
@ -5,9 +5,9 @@ dblink -- Returns a set from a remote database
|
||||
|
||||
Synopsis
|
||||
|
||||
dblink(text connstr, text sql)
|
||||
dblink(text connname, text sql)
|
||||
dblink(text sql)
|
||||
dblink(text connstr, text sql [, bool fail_on_error])
|
||||
dblink(text connname, text sql [, bool fail_on_error])
|
||||
dblink(text sql [, bool fail_on_error])
|
||||
|
||||
Inputs
|
||||
|
||||
@ -25,6 +25,12 @@ Inputs
|
||||
sql statement that you wish to execute on the remote host
|
||||
e.g. "select * from pg_class"
|
||||
|
||||
fail_on_error
|
||||
|
||||
If true (default when not present) then an ERROR thrown on the remote side
|
||||
of the connection causes an ERROR to also be thrown locally. If false, the
|
||||
remote ERROR is locally treated as a NOTICE, and no rows are returned.
|
||||
|
||||
Outputs
|
||||
|
||||
Returns setof record
|
||||
|
@ -128,6 +128,23 @@ WHERE t.a > 7;
|
||||
9 | j | {a9,b9,c9}
|
||||
(2 rows)
|
||||
|
||||
-- open a cursor with bad SQL and fail_on_error set to false
|
||||
SELECT dblink_open('rmt_foo_cursor','SELECT * FROM foobar',false);
|
||||
NOTICE: sql error
|
||||
DETAIL: ERROR: relation "foobar" does not exist
|
||||
|
||||
dblink_open
|
||||
-------------
|
||||
ERROR
|
||||
(1 row)
|
||||
|
||||
-- reset remote transaction state
|
||||
SELECT dblink_exec('ABORT');
|
||||
dblink_exec
|
||||
-------------
|
||||
ROLLBACK
|
||||
(1 row)
|
||||
|
||||
-- open a cursor
|
||||
SELECT dblink_open('rmt_foo_cursor','SELECT * FROM foo');
|
||||
dblink_open
|
||||
@ -135,6 +152,20 @@ SELECT dblink_open('rmt_foo_cursor','SELECT * FROM foo');
|
||||
OK
|
||||
(1 row)
|
||||
|
||||
-- close the cursor
|
||||
SELECT dblink_close('rmt_foo_cursor',false);
|
||||
dblink_close
|
||||
--------------
|
||||
OK
|
||||
(1 row)
|
||||
|
||||
-- open the cursor again
|
||||
SELECT dblink_open('rmt_foo_cursor','SELECT * FROM foo');
|
||||
dblink_open
|
||||
-------------
|
||||
OK
|
||||
(1 row)
|
||||
|
||||
-- fetch some data
|
||||
SELECT *
|
||||
FROM dblink_fetch('rmt_foo_cursor',4) AS t(a int, b text, c text[]);
|
||||
@ -165,11 +196,38 @@ FROM dblink_fetch('rmt_foo_cursor',4) AS t(a int, b text, c text[]);
|
||||
9 | j | {a9,b9,c9}
|
||||
(2 rows)
|
||||
|
||||
-- close the cursor
|
||||
SELECT dblink_close('rmt_foo_cursor');
|
||||
-- intentionally botch a fetch
|
||||
SELECT *
|
||||
FROM dblink_fetch('rmt_foobar_cursor',4,false) AS t(a int, b text, c text[]);
|
||||
NOTICE: sql error
|
||||
DETAIL: ERROR: cursor "rmt_foobar_cursor" does not exist
|
||||
|
||||
a | b | c
|
||||
---+---+---
|
||||
(0 rows)
|
||||
|
||||
-- reset remote transaction state
|
||||
SELECT dblink_exec('ABORT');
|
||||
dblink_exec
|
||||
-------------
|
||||
ROLLBACK
|
||||
(1 row)
|
||||
|
||||
-- close the wrong cursor
|
||||
SELECT dblink_close('rmt_foobar_cursor',false);
|
||||
NOTICE: sql error
|
||||
DETAIL: ERROR: cursor "rmt_foobar_cursor" does not exist
|
||||
|
||||
dblink_close
|
||||
--------------
|
||||
OK
|
||||
ERROR
|
||||
(1 row)
|
||||
|
||||
-- reset remote transaction state
|
||||
SELECT dblink_exec('ABORT');
|
||||
dblink_exec
|
||||
-------------
|
||||
ROLLBACK
|
||||
(1 row)
|
||||
|
||||
-- should generate 'cursor "rmt_foo_cursor" not found' error
|
||||
@ -178,6 +236,16 @@ FROM dblink_fetch('rmt_foo_cursor',4) AS t(a int, b text, c text[]);
|
||||
ERROR: sql error
|
||||
DETAIL: ERROR: cursor "rmt_foo_cursor" does not exist
|
||||
|
||||
-- this time, 'cursor "rmt_foo_cursor" not found' as a notice
|
||||
SELECT *
|
||||
FROM dblink_fetch('rmt_foo_cursor',4,false) AS t(a int, b text, c text[]);
|
||||
NOTICE: sql error
|
||||
DETAIL: ERROR: cursor "rmt_foo_cursor" does not exist
|
||||
|
||||
a | b | c
|
||||
---+---+---
|
||||
(0 rows)
|
||||
|
||||
-- close the persistent connection
|
||||
SELECT dblink_disconnect();
|
||||
dblink_disconnect
|
||||
@ -232,6 +300,23 @@ FROM dblink('SELECT * FROM foo') AS t(a int, b text, c text[]);
|
||||
11 | l | {a11,b11,c11}
|
||||
(12 rows)
|
||||
|
||||
-- bad remote select
|
||||
SELECT *
|
||||
FROM dblink('SELECT * FROM foobar',false) AS t(a int, b text, c text[]);
|
||||
NOTICE: sql error
|
||||
DETAIL: ERROR: relation "foobar" does not exist
|
||||
|
||||
a | b | c
|
||||
---+---+---
|
||||
(0 rows)
|
||||
|
||||
-- reset remote transaction state
|
||||
SELECT dblink_exec('ABORT');
|
||||
dblink_exec
|
||||
-------------
|
||||
ROLLBACK
|
||||
(1 row)
|
||||
|
||||
-- change some data
|
||||
SELECT dblink_exec('UPDATE foo SET f3[2] = ''b99'' WHERE f1 = 11');
|
||||
dblink_exec
|
||||
@ -248,6 +333,23 @@ WHERE a = 11;
|
||||
11 | l | {a11,b99,c11}
|
||||
(1 row)
|
||||
|
||||
-- botch a change to some other data
|
||||
SELECT dblink_exec('UPDATE foobar SET f3[2] = ''b99'' WHERE f1 = 11',false);
|
||||
NOTICE: sql error
|
||||
DETAIL: ERROR: relation "foobar" does not exist
|
||||
|
||||
dblink_exec
|
||||
-------------
|
||||
ERROR
|
||||
(1 row)
|
||||
|
||||
-- reset remote transaction state
|
||||
SELECT dblink_exec('ABORT');
|
||||
dblink_exec
|
||||
-------------
|
||||
ROLLBACK
|
||||
(1 row)
|
||||
|
||||
-- delete some data
|
||||
SELECT dblink_exec('DELETE FROM foo WHERE f1 = 11');
|
||||
dblink_exec
|
||||
@ -298,6 +400,24 @@ WHERE t.a > 7;
|
||||
10 | k | {a10,b10,c10}
|
||||
(3 rows)
|
||||
|
||||
-- use the named persistent connection, but get it wrong
|
||||
SELECT *
|
||||
FROM dblink('myconn','SELECT * FROM foobar',false) AS t(a int, b text, c text[])
|
||||
WHERE t.a > 7;
|
||||
NOTICE: sql error
|
||||
DETAIL: ERROR: relation "foobar" does not exist
|
||||
|
||||
a | b | c
|
||||
---+---+---
|
||||
(0 rows)
|
||||
|
||||
-- reset remote transaction state
|
||||
SELECT dblink_exec('myconn','ABORT');
|
||||
dblink_exec
|
||||
-------------
|
||||
ROLLBACK
|
||||
(1 row)
|
||||
|
||||
-- create a second named persistent connection
|
||||
-- should error with "duplicate connection name"
|
||||
SELECT dblink_connect('myconn','dbname=regression');
|
||||
@ -327,6 +447,23 @@ SELECT dblink_disconnect('myconn2');
|
||||
OK
|
||||
(1 row)
|
||||
|
||||
-- open a cursor incorrectly
|
||||
SELECT dblink_open('myconn','rmt_foo_cursor','SELECT * FROM foobar',false);
|
||||
NOTICE: sql error
|
||||
DETAIL: ERROR: relation "foobar" does not exist
|
||||
|
||||
dblink_open
|
||||
-------------
|
||||
ERROR
|
||||
(1 row)
|
||||
|
||||
-- reset remote transaction state
|
||||
SELECT dblink_exec('myconn','ABORT');
|
||||
dblink_exec
|
||||
-------------
|
||||
ROLLBACK
|
||||
(1 row)
|
||||
|
||||
-- open a cursor
|
||||
SELECT dblink_open('myconn','rmt_foo_cursor','SELECT * FROM foo');
|
||||
dblink_open
|
||||
@ -365,11 +502,21 @@ FROM dblink_fetch('myconn','rmt_foo_cursor',4) AS t(a int, b text, c text[]);
|
||||
10 | k | {a10,b10,c10}
|
||||
(3 rows)
|
||||
|
||||
-- close the cursor
|
||||
SELECT dblink_close('myconn','rmt_foo_cursor');
|
||||
dblink_close
|
||||
--------------
|
||||
OK
|
||||
-- fetch some data incorrectly
|
||||
SELECT *
|
||||
FROM dblink_fetch('myconn','rmt_foobar_cursor',4,false) AS t(a int, b text, c text[]);
|
||||
NOTICE: sql error
|
||||
DETAIL: ERROR: cursor "rmt_foobar_cursor" does not exist
|
||||
|
||||
a | b | c
|
||||
---+---+---
|
||||
(0 rows)
|
||||
|
||||
-- reset remote transaction state
|
||||
SELECT dblink_exec('myconn','ABORT');
|
||||
dblink_exec
|
||||
-------------
|
||||
ROLLBACK
|
||||
(1 row)
|
||||
|
||||
-- should generate 'cursor "rmt_foo_cursor" not found' error
|
||||
|
@ -81,9 +81,21 @@ SELECT *
|
||||
FROM dblink('SELECT * FROM foo') AS t(a int, b text, c text[])
|
||||
WHERE t.a > 7;
|
||||
|
||||
-- open a cursor with bad SQL and fail_on_error set to false
|
||||
SELECT dblink_open('rmt_foo_cursor','SELECT * FROM foobar',false);
|
||||
|
||||
-- reset remote transaction state
|
||||
SELECT dblink_exec('ABORT');
|
||||
|
||||
-- open a cursor
|
||||
SELECT dblink_open('rmt_foo_cursor','SELECT * FROM foo');
|
||||
|
||||
-- close the cursor
|
||||
SELECT dblink_close('rmt_foo_cursor',false);
|
||||
|
||||
-- open the cursor again
|
||||
SELECT dblink_open('rmt_foo_cursor','SELECT * FROM foo');
|
||||
|
||||
-- fetch some data
|
||||
SELECT *
|
||||
FROM dblink_fetch('rmt_foo_cursor',4) AS t(a int, b text, c text[]);
|
||||
@ -95,13 +107,27 @@ FROM dblink_fetch('rmt_foo_cursor',4) AS t(a int, b text, c text[]);
|
||||
SELECT *
|
||||
FROM dblink_fetch('rmt_foo_cursor',4) AS t(a int, b text, c text[]);
|
||||
|
||||
-- close the cursor
|
||||
SELECT dblink_close('rmt_foo_cursor');
|
||||
-- intentionally botch a fetch
|
||||
SELECT *
|
||||
FROM dblink_fetch('rmt_foobar_cursor',4,false) AS t(a int, b text, c text[]);
|
||||
|
||||
-- reset remote transaction state
|
||||
SELECT dblink_exec('ABORT');
|
||||
|
||||
-- close the wrong cursor
|
||||
SELECT dblink_close('rmt_foobar_cursor',false);
|
||||
|
||||
-- reset remote transaction state
|
||||
SELECT dblink_exec('ABORT');
|
||||
|
||||
-- should generate 'cursor "rmt_foo_cursor" not found' error
|
||||
SELECT *
|
||||
FROM dblink_fetch('rmt_foo_cursor',4) AS t(a int, b text, c text[]);
|
||||
|
||||
-- this time, 'cursor "rmt_foo_cursor" not found' as a notice
|
||||
SELECT *
|
||||
FROM dblink_fetch('rmt_foo_cursor',4,false) AS t(a int, b text, c text[]);
|
||||
|
||||
-- close the persistent connection
|
||||
SELECT dblink_disconnect();
|
||||
|
||||
@ -125,6 +151,13 @@ SELECT substr(dblink_exec('INSERT INTO foo VALUES(11,''l'',''{"a11","b11","c11"}
|
||||
SELECT *
|
||||
FROM dblink('SELECT * FROM foo') AS t(a int, b text, c text[]);
|
||||
|
||||
-- bad remote select
|
||||
SELECT *
|
||||
FROM dblink('SELECT * FROM foobar',false) AS t(a int, b text, c text[]);
|
||||
|
||||
-- reset remote transaction state
|
||||
SELECT dblink_exec('ABORT');
|
||||
|
||||
-- change some data
|
||||
SELECT dblink_exec('UPDATE foo SET f3[2] = ''b99'' WHERE f1 = 11');
|
||||
|
||||
@ -133,6 +166,12 @@ SELECT *
|
||||
FROM dblink('SELECT * FROM foo') AS t(a int, b text, c text[])
|
||||
WHERE a = 11;
|
||||
|
||||
-- botch a change to some other data
|
||||
SELECT dblink_exec('UPDATE foobar SET f3[2] = ''b99'' WHERE f1 = 11',false);
|
||||
|
||||
-- reset remote transaction state
|
||||
SELECT dblink_exec('ABORT');
|
||||
|
||||
-- delete some data
|
||||
SELECT dblink_exec('DELETE FROM foo WHERE f1 = 11');
|
||||
|
||||
@ -161,6 +200,14 @@ SELECT *
|
||||
FROM dblink('myconn','SELECT * FROM foo') AS t(a int, b text, c text[])
|
||||
WHERE t.a > 7;
|
||||
|
||||
-- use the named persistent connection, but get it wrong
|
||||
SELECT *
|
||||
FROM dblink('myconn','SELECT * FROM foobar',false) AS t(a int, b text, c text[])
|
||||
WHERE t.a > 7;
|
||||
|
||||
-- reset remote transaction state
|
||||
SELECT dblink_exec('myconn','ABORT');
|
||||
|
||||
-- create a second named persistent connection
|
||||
-- should error with "duplicate connection name"
|
||||
SELECT dblink_connect('myconn','dbname=regression');
|
||||
@ -176,6 +223,12 @@ WHERE t.a > 7;
|
||||
-- close the second named persistent connection
|
||||
SELECT dblink_disconnect('myconn2');
|
||||
|
||||
-- open a cursor incorrectly
|
||||
SELECT dblink_open('myconn','rmt_foo_cursor','SELECT * FROM foobar',false);
|
||||
|
||||
-- reset remote transaction state
|
||||
SELECT dblink_exec('myconn','ABORT');
|
||||
|
||||
-- open a cursor
|
||||
SELECT dblink_open('myconn','rmt_foo_cursor','SELECT * FROM foo');
|
||||
|
||||
@ -190,8 +243,12 @@ FROM dblink_fetch('myconn','rmt_foo_cursor',4) AS t(a int, b text, c text[]);
|
||||
SELECT *
|
||||
FROM dblink_fetch('myconn','rmt_foo_cursor',4) AS t(a int, b text, c text[]);
|
||||
|
||||
-- close the cursor
|
||||
SELECT dblink_close('myconn','rmt_foo_cursor');
|
||||
-- fetch some data incorrectly
|
||||
SELECT *
|
||||
FROM dblink_fetch('myconn','rmt_foobar_cursor',4,false) AS t(a int, b text, c text[]);
|
||||
|
||||
-- reset remote transaction state
|
||||
SELECT dblink_exec('myconn','ABORT');
|
||||
|
||||
-- should generate 'cursor "rmt_foo_cursor" not found' error
|
||||
SELECT *
|
||||
|
Loading…
x
Reference in New Issue
Block a user