summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Conway <mail@joeconway.com>2010-02-03 23:02:39 +0000
committerJoe Conway <mail@joeconway.com>2010-02-03 23:02:39 +0000
commitc3f8e037c0238a8132ed4245ced956a20db82635 (patch)
tree64b7ce4054cc0dc696445c43bdb7187338dae27e
parent9d4269f087d94c868d4da72d14bdf89617b0246c (diff)
downloadpostgresql-REL7_3_STABLE.tar.gz
Check to ensure the number of primary key fields supplied does notREL7_3_STABLE
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.
-rw-r--r--contrib/dblink/dblink.c52
-rw-r--r--contrib/dblink/expected/dblink.out9
-rw-r--r--contrib/dblink/sql/dblink.sql6
3 files changed, 67 insertions, 0 deletions
diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c
index 2ed84da217..b901c3941f 100644
--- a/contrib/dblink/dblink.c
+++ b/contrib/dblink/dblink.c
@@ -76,6 +76,7 @@ static void remove_res_ptr(dblink_results * results);
static char *generate_relation_name(Oid relid);
static char *connstr_strip_password(const char *connstr);
static void dblink_security_check(PGconn *conn, const char *connstr);
+static int get_nondropped_natts(Oid relid);
/* Global */
List *res_id = NIL;
@@ -1100,6 +1101,7 @@ dblink_build_sql_insert(PG_FUNCTION_ARGS)
int16 typlen;
bool typbyval;
char typalign;
+ int nondropped_natts;
relname_text = PG_GETARG_TEXT_P(0);
@@ -1123,6 +1125,14 @@ dblink_build_sql_insert(PG_FUNCTION_ARGS)
if (pknumatts == 0)
elog(ERROR, "dblink_build_sql_insert: number of key attributes must be > 0.");
+ /*
+ * 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)
+ elog(ERROR, "number of primary key fields exceeds number of specified relation attributes");
+
src_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(3);
tgt_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(4);
@@ -1239,6 +1249,7 @@ dblink_build_sql_delete(PG_FUNCTION_ARGS)
int16 typlen;
bool typbyval;
char typalign;
+ int nondropped_natts;
relname_text = PG_GETARG_TEXT_P(0);
@@ -1262,6 +1273,14 @@ dblink_build_sql_delete(PG_FUNCTION_ARGS)
if (pknumatts == 0)
elog(ERROR, "dblink_build_sql_insert: number of key attributes must be > 0.");
+ /*
+ * 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)
+ elog(ERROR, "number of primary key fields exceeds number of specified relation attributes");
+
tgt_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(3);
/*
@@ -1356,6 +1375,7 @@ dblink_build_sql_update(PG_FUNCTION_ARGS)
int16 typlen;
bool typbyval;
char typalign;
+ int nondropped_natts;
relname_text = PG_GETARG_TEXT_P(0);
@@ -1379,6 +1399,14 @@ dblink_build_sql_update(PG_FUNCTION_ARGS)
if (pknumatts == 0)
elog(ERROR, "dblink_build_sql_insert: number of key attributes must be > 0.");
+ /*
+ * 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)
+ elog(ERROR, "number of primary key fields exceeds number of specified relation attributes");
+
src_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(3);
tgt_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(4);
@@ -2191,3 +2219,27 @@ dblink_security_check(PGconn *conn, const char *connstr)
PQfinish(conn);
}
}
+
+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 ed3a87cfa0..326fc9f40d 100644
--- a/contrib/dblink/expected/dblink.out
+++ b/contrib/dblink/expected/dblink.out
@@ -44,6 +44,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"}');
@@ -52,6 +55,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
@@ -59,6 +65,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 4d534e50c1..454e1dab11 100644
--- a/contrib/dblink/sql/dblink.sql
+++ b/contrib/dblink/sql/dblink.sql
@@ -36,13 +36,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";