8000 Check to ensure the number of primary key fields supplied does not · danielcode/postgres@c3f8e03 · GitHub
[go: up one dir, main page]

Skip to content

Commit c3f8e03

Browse files
committed
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.
1 parent 9d4269f commit c3f8e03

File tree

3 files changed

+67
-0
lines changed

3 files changed

+67
-0
lines changed

contrib/dblink/dblink.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ static void remove_res_ptr(dblink_results * results);
7676
static char *generate_relation_name(Oid relid);
7777
static char *connstr_strip_password(const char *connstr);
7878
static void dblink_security_check(PGconn *conn, const char *connstr);
79+
static int get_nondropped_natts(Oid relid);
7980

8081
/* Global */
8182
List *res_id = NIL;
@@ -1100,6 +1101,7 @@ dblink_build_sql_insert(PG_FUNCTION_ARGS)
11001101
int16 typlen;
11011102
bool typbyval;
11021103
char typalign;
1104+
int nondropped_natts;
11031105

11041106
relname_text = PG_GETARG_TEXT_P(0);
11051107

@@ -1123,6 +1125,14 @@ dblink_build_sql_insert(PG_FUNCTION_ARGS)
11231125
if (pknumatts == 0)
11241126
elog(ERROR, "dblink_build_sql_insert: number of key attributes must be > 0.");
11251127

1128+
/*
1129+
* ensure we don't ask for more pk attributes than we have
1130+
* non-dropped columns
1131+
*/
1132+
nondropped_natts = get_nondropped_natts(relid);
1133+
if (pknumatts > nondropped_natts)
1134+
elog(ERROR, "number of primary key fields exceeds number of specified relation attributes");
1135+
11261136
src_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(3);
11271137
tgt_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(4);
11281138

@@ -1239,6 +1249,7 @@ dblink_build_sql_delete(PG_FUNCTION_ARGS)
12391249
int16 typlen;
12401250
bool typbyval;
12411251
char typalign;
1252+
int nondropped_natts;
12421253

12431254
relname_text = PG_GETARG_TEXT_P(0);
12441255

@@ -1262,6 +1273,14 @@ dblink_build_sql_delete(PG_FUNCTION_ARGS)
12621273
if (pknumatts == 0)
12631274
elog(ERROR, "dblink_build_sql_insert: number of key attributes must be > 0.");
12641275

1276+
/*
1277+
* ensure we don't ask for more pk attributes than we have
1278+
* non-dropped columns
1279+
*/
1280+
nondropped_natts = get_nondropped_natts(relid);
1281+
if (pknumatts > nondropped_natts)
1282+
elog(ERROR, "number of primary key fields exceeds number of specified relation attributes");
1283+
12651284
tgt_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(3);
12661285

12671286
/*
@@ -1356,6 +1375,7 @@ dblink_build_sql_update(PG_FUNCTION_ARGS)
13561375
int16 typlen;
13571376
bool typbyval;
13581377
char typalign;
1378+
int nondropped_natts;
13591379

13601380
relname_text = PG_GETARG_TEXT_P(0);
13611381

@@ -1379,6 +1399,14 @@ dblink_build_sql_update(PG_FUNCTION_ARGS)
13791399
if (pknumatts == 0)
13801400
elog(ERROR, "dblink_build_sql_insert: number of key attributes must be > 0.");
13811401

1402+
/*
1403+
* ensure we don't ask for more pk attributes than we have
1404+
* non-dropped columns
1405+
*/
1406+
nondropped_natts = get_nondropped_natts(relid);
1407+
if (pknumatts > nondropped_natts)
1408+
elog(ERROR, "number of primary key fields exceeds number of specified relation attributes");
1409+
13821410
src_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(3);
13831411
tgt_pkattvals_arry = PG_GETARG_ARRAYTYPE_P(4);
13841412

@@ -2191,3 +2219,27 @@ dblink_security_check(PGconn *conn, const char *connstr)
21912219
PQfinish(conn);
21922220
}
21932221
}
2222+
2223+
static int
2224+
get_nondropped_natts(Oid relid)
2225+
{
2226+
int nondropped_natts = 0;
2227+
TupleDesc tupdesc;
2228+
Relation rel;
2229+
int natts;
2230+
int i;
2231+
2232+
rel = relation_open(relid, AccessShareLock);
2233+
tupdesc = rel->rd_att;
2234+
natts = tupdesc->natts;
2235+
2236+
for (i = 0; i < natts; i++)
2237+
{
2238+
if (tupdesc->attrs[i]->attisdropped)
2239+
continue;
2240+
nondropped_natts++;
2241+
}
2242+
2243+
relation_close(rel, AccessShareLock);
2244+
return nondropped_natts;
2245+
}

contrib/dblink/expected/dblink.out

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ SELECT dblink_build_sql_insert('foo','1 2',2,'{"0", "a"}','{"99", "xyz"}');
4444
INSERT INTO foo(f1,f2,f3) VALUES('99','xyz','{a0,b0,c0}')
4545
(1 row)
4646

47+
-- too many pk fields, should fail
48+
SELECT dblink_build_sql_insert('foo','1 2 3 4',4,'{"0", "a", "{a0,b0,c0}"}','{"99", "xyz", "{za0,zb0,zc0}"}');
49+
ERROR: number of primary key fields exceeds number of specified relation attributes
4750
-- build an update statement based on a local tuple,
4851
-- replacing the primary key values with new ones
4952
SELECT dblink_build_sql_update('foo','1 2',2,'{"0", "a"}','{"99", "xyz"}');
@@ -52,13 +55,19 @@ SELECT dblink_build_sql_update('foo','1 2',2,'{"0", "a"}','{"99", "xyz"}');
5255
UPDATE foo SET f1 = '99', f2 = 'xyz', f3 = '{a0,b0,c0}' WHERE f1 = '99' AND f2 = 'xyz'
5356
(1 row)
5457

58+
-- too many pk fields, should fail
59+
SELECT dblink_build_sql_update('foo','1 2 3 4',4,'{"0", "a", "{a0,b0,c0}"}','{"99", "xyz", "{za0,zb0,zc0}"}');
60+
ERROR: number of primary key fields exceeds number of specified relation attributes
5561
-- build a delete statement based on a local tuple,
5662
SELECT dblink_build_sql_delete('foo','1 2',2,'{"0", "a"}');
5763
dblink_build_sql_delete
5864
---------------------------------------------
5965
DELETE FROM foo WHERE f1 = '0' AND f2 = 'a'
6066
(1 row)
6167

68+
-- too many pk fields, should fail
69+
SELECT dblink_build_sql_delete('foo','1 2 3 4',4,'{"0", "a", "{a0,b0,c0}"}');
70+
ERROR: number of primary key fields exceeds number of specified relation attributes
6271
-- retest using a quoted and schema qualified table
6372
CREATE SCHEMA "MySchema";
6473
CREATE TABLE "MySchema"."Foo"(f1 int, f2 text, f3 text[], primary key (f1,f2));

contrib/dblink/sql/dblink.sql

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,19 @@ FROM dblink_get_pkey('foo');
3636
-- build an insert statement based on a local tuple,
3737
-- replacing the primary key values with new ones
3838
SELECT dblink_build_sql_insert('foo','1 2',2,'{"0", "a"}',&# 962F 39;{"99", "xyz"}');
39+
-- too many pk fields, should fail
40+
SELECT dblink_build_sql_insert('foo','1 2 3 4',4,'{"0", "a", "{a0,b0,c0}"}','{"99", "xyz", "{za0,zb0,zc0}"}');
3941

4042
-- build an update statement based on a local tuple,
4143
-- replacing the primary key values with new ones
4244
SELECT dblink_build_sql_update('foo','1 2',2,'{"0", "a"}','{"99", "xyz"}');
45+
-- too many pk fields, should fail
46+
SELECT dblink_build_sql_update('foo','1 2 3 4',4,'{"0", "a", "{a0,b0,c0}"}','{"99", "xyz", "{za0,zb0,zc0}"}');
4347

4448
-- build a delete statement based on a local tuple,
4549
SELECT dblink_build_sql_delete('foo','1 2',2,'{"0", "a"}');
50+
-- too many pk fields, should fail
51+
SELECT dblink_build_sql_delete('foo','1 2 3 4',4,'{"0", "a", "{a0,b0,c0}"}');
4652

4753
-- retest using a quoted and schema qualified table
4854
CREATE SCHEMA "MySchema";

0 commit comments

Comments
 (0)
0