summaryrefslogtreecommitdiff
path: root/contrib/dblink
diff options
context:
space:
mode:
authorJoe Conway <mail@joeconway.com>2010-02-03 23:01:11 +0000
committerJoe Conway <mail@joeconway.com>2010-02-03 23:01:11 +0000
commitfdac8cf998b9a41fa2b64cb3a80bc02548189082 (patch)
tree493fba8a3a4fd6c16fa5a1fa0052a51d6efc024a /contrib/dblink
parent73a835eea079a012f51fe8be78282e6e3b66210f (diff)
downloadpostgresql-fdac8cf998b9a41fa2b64cb3a80bc02548189082.tar.gz
Check to ensure the number of primary key fields supplied does not
exceed the total number of non-dropped source table fields for dblink_build_sql_*(). Addresses bug report from Rushabh Lathia. Backpatch all the way to the 7.3 branch.
Diffstat (limited to 'contrib/dblink')
-rw-r--r--contrib/dblink/dblink.c58
-rw-r--r--contrib/dblink/expected/dblink.out9
-rw-r--r--contrib/dblink/sql/dblink.sql6
3 files changed, 72 insertions, 1 deletions
diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c
index ded7832f33..9806160be2 100644
--- a/contrib/dblink/dblink.c
+++ b/contrib/dblink/dblink.c
@@ -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.87 2010/01/24 22:19:38 joe Exp $
+ * $PostgreSQL: pgsql/contrib/dblink/dblink.c,v 1.88 2010/02/03 23:01:11 joe Exp $
* Copyright (c) 2001-2010, PostgreSQL Global Development Group
* ALL RIGHTS RESERVED;
*
@@ -101,6 +101,7 @@ static void dblink_security_check(PGconn *conn, remoteConn *rconn);
static void dblink_res_error(const char *conname, PGresult *res, const char *dblink_context_msg, bool fail);
static char *get_connect_string(const char *servername);
static char *escape_param_str(const char *from);
+static int get_nondropped_natts(Oid relid);
/* Global */
static remoteConn *pconn = NULL;
@@ -1262,6 +1263,7 @@ dblink_build_sql_insert(PG_FUNCTION_ARGS)
int src_nitems;
int tgt_nitems;
char *sql;
+ int nondropped_natts;
/*
* Convert relname to rel OID.
@@ -1290,6 +1292,15 @@ dblink_build_sql_insert(PG_FUNCTION_ARGS)
"attributes too large")));
/*
+ * ensure we don't ask for more pk attributes than we have
+ * non-dropped columns
+ */
+ nondropped_natts = get_nondropped_natts(relid);
+ if (pknumatts > nondropped_natts)
+ ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("number of primary key fields exceeds number of specified relation attributes")));
+
+ /*
* Source array is made up of key values that will be used to locate the
* tuple of interest from the local system.
*/
@@ -1354,6 +1365,7 @@ dblink_build_sql_delete(PG_FUNCTION_ARGS)
int2vector *pkattnums = (int2vector *) PG_GETARG_POINTER(1);
int32 pknumatts_tmp = PG_GETARG_INT32(2);
ArrayType *tgt_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(3);
+ int nondropped_natts;
Oid relid;
int16 pknumatts = 0;
char **tgt_pkattvals;
@@ -1387,6 +1399,15 @@ dblink_build_sql_delete(PG_FUNCTION_ARGS)
"attributes too large")));
/*
+ * ensure we don't ask for more pk attributes than we have
+ * non-dropped columns
+ */
+ nondropped_natts = get_nondropped_natts(relid);
+ if (pknumatts > nondropped_natts)
+ ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("number of primary key fields exceeds number of specified relation attributes")));
+
+ /*
* Target array is made up of key values that will be used to build the
* SQL string for use on the remote system.
*/
@@ -1441,6 +1462,7 @@ dblink_build_sql_update(PG_FUNCTION_ARGS)
int32 pknumatts_tmp = PG_GETARG_INT32(2);
ArrayType *src_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(3);
ArrayType *tgt_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(4);
+ int nondropped_natts;
Oid relid;
int16 pknumatts = 0;
char **src_pkattvals;
@@ -1476,6 +1498,15 @@ dblink_build_sql_update(PG_FUNCTION_ARGS)
"attributes too large")));
/*
+ * ensure we don't ask for more pk attributes than we have
+ * non-dropped columns
+ */
+ nondropped_natts = get_nondropped_natts(relid);
+ if (pknumatts > nondropped_natts)
+ ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("number of primary key fields exceeds number of specified relation attributes")));
+
+ /*
* Source array is made up of key values that will be used to locate the
* tuple of interest from the local system.
*/
@@ -2442,3 +2473,28 @@ escape_param_str(const char *str)
return buf->data;
}
+
+static int
+get_nondropped_natts(Oid relid)
+{
+ int nondropped_natts = 0;
+ TupleDesc tupdesc;
+ Relation rel;
+ int natts;
+ int i;
+
+ rel = relation_open(relid, AccessShareLock);
+ tupdesc = rel->rd_att;
+ natts = tupdesc->natts;
+
+ for (i = 0; i < natts; i++)
+ {
+ if (tupdesc->attrs[i]->attisdropped)
+ continue;
+ nondropped_natts++;
+ }
+
+ relation_close(rel, AccessShareLock);
+ return nondropped_natts;
+}
+
diff --git a/contrib/dblink/expected/dblink.out b/contrib/dblink/expected/dblink.out
index d39aa45373..7aa8cc8b0d 100644
--- a/contrib/dblink/expected/dblink.out
+++ b/contrib/dblink/expected/dblink.out
@@ -39,6 +39,9 @@ SELECT dblink_build_sql_insert('foo','1 2',2,'{"0", "a"}','{"99", "xyz"}');
INSERT INTO foo(f1,f2,f3) VALUES('99','xyz','{a0,b0,c0}')
(1 row)
+-- too many pk fields, should fail
+SELECT dblink_build_sql_insert('foo','1 2 3 4',4,'{"0", "a", "{a0,b0,c0}"}','{"99", "xyz", "{za0,zb0,zc0}"}');
+ERROR: number of primary key fields exceeds number of specified relation attributes
-- build an update statement based on a local tuple,
-- replacing the primary key values with new ones
SELECT dblink_build_sql_update('foo','1 2',2,'{"0", "a"}','{"99", "xyz"}');
@@ -47,6 +50,9 @@ SELECT dblink_build_sql_update('foo','1 2',2,'{"0", "a"}','{"99", "xyz"}');
UPDATE foo SET f1 = '99', f2 = 'xyz', f3 = '{a0,b0,c0}' WHERE f1 = '99' AND f2 = 'xyz'
(1 row)
+-- too many pk fields, should fail
+SELECT dblink_build_sql_update('foo','1 2 3 4',4,'{"0", "a", "{a0,b0,c0}"}','{"99", "xyz", "{za0,zb0,zc0}"}');
+ERROR: number of primary key fields exceeds number of specified relation attributes
-- build a delete statement based on a local tuple,
SELECT dblink_build_sql_delete('foo','1 2',2,'{"0", "a"}');
dblink_build_sql_delete
@@ -54,6 +60,9 @@ SELECT dblink_build_sql_delete('foo','1 2',2,'{"0", "a"}');
DELETE FROM foo WHERE f1 = '0' AND f2 = 'a'
(1 row)
+-- too many pk fields, should fail
+SELECT dblink_build_sql_delete('foo','1 2 3 4',4,'{"0", "a", "{a0,b0,c0}"}');
+ERROR: number of primary key fields exceeds number of specified relation attributes
-- retest using a quoted and schema qualified table
CREATE SCHEMA "MySchema";
CREATE TABLE "MySchema"."Foo"(f1 int, f2 text, f3 text[], primary key (f1,f2));
diff --git a/contrib/dblink/sql/dblink.sql b/contrib/dblink/sql/dblink.sql
index d0ad87695a..dd68239d3f 100644
--- a/contrib/dblink/sql/dblink.sql
+++ b/contrib/dblink/sql/dblink.sql
@@ -34,13 +34,19 @@ FROM dblink_get_pkey('foo');
-- build an insert statement based on a local tuple,
-- replacing the primary key values with new ones
SELECT dblink_build_sql_insert('foo','1 2',2,'{"0", "a"}','{"99", "xyz"}');
+-- too many pk fields, should fail
+SELECT dblink_build_sql_insert('foo','1 2 3 4',4,'{"0", "a", "{a0,b0,c0}"}','{"99", "xyz", "{za0,zb0,zc0}"}');
-- build an update statement based on a local tuple,
-- replacing the primary key values with new ones
SELECT dblink_build_sql_update('foo','1 2',2,'{"0", "a"}','{"99", "xyz"}');
+-- too many pk fields, should fail
+SELECT dblink_build_sql_update('foo','1 2 3 4',4,'{"0", "a", "{a0,b0,c0}"}','{"99", "xyz", "{za0,zb0,zc0}"}');
-- build a delete statement based on a local tuple,
SELECT dblink_build_sql_delete('foo','1 2',2,'{"0", "a"}');
+-- too many pk fields, should fail
+SELECT dblink_build_sql_delete('foo','1 2 3 4',4,'{"0", "a", "{a0,b0,c0}"}');
-- retest using a quoted and schema qualified table
CREATE SCHEMA "MySchema";