summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Conway2006-01-03 23:48:04 +0000
committerJoe Conway2006-01-03 23:48:04 +0000
commitfcacfc96a2e13e1abe920f4a94a2fc51b5853c71 (patch)
treef498125ffca751e05e4ca313949b1e104b2111f7
parent8dc7c8cf1dc38a96cff8cf9c2c5e90f678e67420 (diff)
When the remote query result has a different number of columns
than the local query specifies (e.g. in the FROM clause), throw an ERROR (instead of crashing). Fix for bug #2129 reported by Akio Iwaasa.
-rw-r--r--contrib/dblink/dblink.c40
-rw-r--r--contrib/dblink/doc/cursor7
2 files changed, 39 insertions, 8 deletions
diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c
index 3fea501b60c..dbaebc88552 100644
--- a/contrib/dblink/dblink.c
+++ b/contrib/dblink/dblink.c
@@ -446,10 +446,6 @@ dblink_fetch(PG_FUNCTION_ARGS)
/* got results, keep track of them */
funcctx->user_fctx = res;
- /* fast track when no results */
- if (funcctx->max_calls < 1)
- SRF_RETURN_DONE(funcctx);
-
/* check typtype to see if we have a predetermined return type */
functypeid = get_func_rettype(funcid);
functyptype = get_typtype(functypeid);
@@ -474,6 +470,22 @@ dblink_fetch(PG_FUNCTION_ARGS)
/* store needed metadata for subsequent calls */
slot = TupleDescGetSlot(tupdesc);
funcctx->slot = slot;
+
+ /* check result and tuple descriptor have the same number of columns */
+ if (PQnfields(res) != tupdesc->natts)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("remote query result rowtype does not match "
+ "the specified FROM clause rowtype")));
+
+ /* fast track when no results */
+ if (funcctx->max_calls < 1)
+ {
+ if (res)
+ PQclear(res);
+ SRF_RETURN_DONE(funcctx);
+ }
+
attinmeta = TupleDescGetAttInMetadata(tupdesc);
funcctx->attinmeta = attinmeta;
@@ -617,10 +629,6 @@ dblink_record(PG_FUNCTION_ARGS)
if (freeconn && PG_NARGS() == 2)
PQfinish(conn);
- /* fast track when no results */
- if (funcctx->max_calls < 1)
- SRF_RETURN_DONE(funcctx);
-
/* check typtype to see if we have a predetermined return type */
functypeid = get_func_rettype(funcid);
functyptype = get_typtype(functypeid);
@@ -648,6 +656,22 @@ dblink_record(PG_FUNCTION_ARGS)
/* store needed metadata for subsequent calls */
slot = TupleDescGetSlot(tupdesc);
funcctx->slot = slot;
+
+ /* check result and tuple descriptor have the same number of columns */
+ if (PQnfields(res) != tupdesc->natts)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("remote query result rowtype does not match "
+ "the specified FROM clause rowtype")));
+
+ /* fast track when no results */
+ if (funcctx->max_calls < 1)
+ {
+ if (res)
+ PQclear(res);
+ SRF_RETURN_DONE(funcctx);
+ }
+
attinmeta = TupleDescGetAttInMetadata(tupdesc);
funcctx->attinmeta = attinmeta;
diff --git a/contrib/dblink/doc/cursor b/contrib/dblink/doc/cursor
index 7c9cc3cde25..bf591a4d6e5 100644
--- a/contrib/dblink/doc/cursor
+++ b/contrib/dblink/doc/cursor
@@ -79,6 +79,13 @@ Outputs
Returns setof record
+Note
+
+ On a mismatch between the number of return fields as specified in the FROM
+ clause, and the actual number of fields returned by the remote cursor, an
+ ERROR will be thrown. In this event, the remote cursor is still advanced
+ by as many rows as it would have been if the ERROR had not occurred.
+
Example usage
test=# select dblink_connect('dbname=template1');