diff options
Diffstat (limited to 'contrib/dblink/dblink.c')
-rw-r--r-- | contrib/dblink/dblink.c | 52 |
1 files changed, 52 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; +} |