aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/copy.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2009-02-06 21:15:12 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2009-02-06 21:15:12 +0000
commit7449427a1e6a099bc7e76164cb99a01d5e87237b (patch)
tree05883ab8f6d2c91c3b75892ab566bfac84ff0b59 /src/backend/commands/copy.c
parent0274e1b9499d98c66182321aafb829faa5f49e41 (diff)
downloadpostgresql-7449427a1e6a099bc7e76164cb99a01d5e87237b.tar.gz
postgresql-7449427a1e6a099bc7e76164cb99a01d5e87237b.zip
Clean up some loose ends from the column privileges patch: add
has_column_privilege and has_any_column_privilege SQL functions; fix the information_schema views that are supposed to pay attention to column privileges; adjust pg_stats to show stats for any column you have select privilege on; and fix COPY to allow copying a subset of columns if the user has suitable per-column privileges for all the columns. To improve efficiency of some of the information_schema views, extend the has_xxx_privilege functions to allow inquiring about the OR of a set of privileges in just one call. This is just exposing capability that already existed in the underlying aclcheck routines. In passing, make the information_schema views report the owner's own privileges as being grantable, since Postgres assumes this even when the grant option bit is not set in the ACL. This is a longstanding oversight. Also, make the new has_xxx_privilege functions for foreign data objects follow the same coding conventions used by the older ones. Stephen Frost and Tom Lane
Diffstat (limited to 'src/backend/commands/copy.c')
-rw-r--r--src/backend/commands/copy.c39
1 files changed, 28 insertions, 11 deletions
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index c2e2c822052..550e7e661fd 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.304 2009/01/02 20:42:00 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.305 2009/02/06 21:15:11 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -711,7 +711,7 @@ CopyLoadRawBuf(CopyState cstate)
* or write to a file.
*
* Do not allow the copy if user doesn't have proper permission to access
- * the table.
+ * the table or the specifically requested columns.
*/
uint64
DoCopy(const CopyStmt *stmt, const char *queryString)
@@ -723,7 +723,8 @@ DoCopy(const CopyStmt *stmt, const char *queryString)
List *force_quote = NIL;
List *force_notnull = NIL;
AclMode required_access = (is_from ? ACL_INSERT : ACL_SELECT);
- AclResult aclresult;
+ AclMode relPerms;
+ AclMode remainingPerms;
ListCell *option;
TupleDesc tupDesc;
int num_phys_attrs;
@@ -973,13 +974,31 @@ DoCopy(const CopyStmt *stmt, const char *queryString)
cstate->rel = heap_openrv(stmt->relation,
(is_from ? RowExclusiveLock : AccessShareLock));
+ tupDesc = RelationGetDescr(cstate->rel);
+
/* Check relation permissions. */
- aclresult = pg_class_aclcheck(RelationGetRelid(cstate->rel),
- GetUserId(),
- required_access);
- if (aclresult != ACLCHECK_OK)
- aclcheck_error(aclresult, ACL_KIND_CLASS,
- RelationGetRelationName(cstate->rel));
+ relPerms = pg_class_aclmask(RelationGetRelid(cstate->rel), GetUserId(),
+ required_access, ACLMASK_ALL);
+ remainingPerms = required_access & ~relPerms;
+ if (remainingPerms != 0)
+ {
+ /* We don't have table permissions, check per-column permissions */
+ List *attnums;
+ ListCell *cur;
+
+ attnums = CopyGetAttnums(tupDesc, cstate->rel, attnamelist);
+ foreach(cur, attnums)
+ {
+ int attnum = lfirst_int(cur);
+
+ if (pg_attribute_aclcheck(RelationGetRelid(cstate->rel),
+ attnum,
+ GetUserId(),
+ remainingPerms) != ACLCHECK_OK)
+ aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_CLASS,
+ RelationGetRelationName(cstate->rel));
+ }
+ }
/* check read-only transaction */
if (XactReadOnly && is_from &&
@@ -994,8 +1013,6 @@ DoCopy(const CopyStmt *stmt, const char *queryString)
(errcode(ERRCODE_UNDEFINED_COLUMN),
errmsg("table \"%s\" does not have OIDs",
RelationGetRelationName(cstate->rel))));
-
- tupDesc = RelationGetDescr(cstate->rel);
}
else
{