1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-29 10:41:53 +03:00

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.
This commit is contained in:
Joe Conway
2010-02-03 23:01:23 +00:00
parent 4204ff3363
commit 14b22354e4
3 changed files with 72 additions and 1 deletions

View File

@ -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.82.2.1 2009/09/12 23:21:13 joe Exp $
* $PostgreSQL: pgsql/contrib/dblink/dblink.c,v 1.82.2.2 2010/02/03 23:01:23 joe Exp $
* Copyright (c) 2001-2009, PostgreSQL Global Development Group
* ALL RIGHTS RESERVED;
*
@ -100,6 +100,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;
@ -1367,6 +1368,7 @@ dblink_build_sql_insert(PG_FUNCTION_ARGS)
int src_nitems;
int tgt_nitems;
char *sql;
int nondropped_natts;
/*
* Convert relname to rel OID.
@ -1394,6 +1396,15 @@ dblink_build_sql_insert(PG_FUNCTION_ARGS)
errmsg("input for number of primary key " \
"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.
@ -1459,6 +1470,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;
@ -1491,6 +1503,15 @@ dblink_build_sql_delete(PG_FUNCTION_ARGS)
errmsg("input for number of primary key " \
"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.
@ -1546,6 +1567,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;
@ -1580,6 +1602,15 @@ dblink_build_sql_update(PG_FUNCTION_ARGS)
errmsg("input for number of primary key " \
"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.
@ -2467,3 +2498,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;
}