Tom, all,
In the attached patch-
* Tom Lane ([email protected]) wrote:
> * Some of the information_schema views are specified to respond to
> per-column privileges; the column_privileges and columns views
> certainly need work now to meet spec, and there might be others.
Done.
> * It might be appropriate to let the pg_stats view expose stats for
> columns you have select privilege for, even if you haven't got it
> across the whole table.
Done.
> * We probably ought to invent has_column_privilege SQL functions
> analogous to has_table_privilege; this is not just for completeness,
> but is probably necessary to finish the above items.
Done.
> * ISTM that COPY with a column list should succeed if you have
> SELECT or INSERT privilege on just the mentioned columns.
Done.
> * Perhaps it would be appropriate to let LOCK TABLE succeed if you have
> proper permissions on at least one column of the table. However, it's
> bad enough that LOCK TABLE examines permissions before locking the table
> now; I don't think it ought to be grovelling through the columns without
> lock. So this might be a place to leave well enough alone.
Left alone.
Thanks,
Stephen
Index: src/backend/catalog/information_schema.sql
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/catalog/information_schema.sql,v
retrieving revision 1.50
diff -c -r1.50 information_schema.sql
*** src/backend/catalog/information_schema.sql 20 Jan 2009 09:10:20 -0000 1.50
--- src/backend/catalog/information_schema.sql 3 Feb 2009 03:17:26 -0000
***************
*** 507,523 ****
UNION ALL
SELECT 0::oid, 'PUBLIC'
) AS grantee (oid, rolname),
! (SELECT 'SELECT' UNION ALL
! SELECT 'INSERT' UNION ALL
! SELECT 'UPDATE' UNION ALL
! SELECT 'REFERENCES') AS pr (type)
WHERE a.attrelid = c.oid
AND c.relnamespace = nc.oid
AND a.attnum > 0
AND NOT a.attisdropped
AND c.relkind IN ('r', 'v')
! AND aclcontains(c.relacl,
makeaclitem(grantee.oid, u_grantor.oid, pr.type, false))
AND (pg_has_role(u_grantor.oid, 'USAGE')
OR pg_has_role(grantee.oid, 'USAGE')
--- 507,523 ----
UNION ALL
SELECT 0::oid, 'PUBLIC'
) AS grantee (oid, rolname),
! (VALUES ('SELECT'),
! ('INSERT'),
! ('UPDATE'),
! ('REFERENCES')) AS pr (type)
WHERE a.attrelid = c.oid
AND c.relnamespace = nc.oid
AND a.attnum > 0
AND NOT a.attisdropped
AND c.relkind IN ('r', 'v')
! AND aclcontains(a.attacl,
makeaclitem(grantee.oid, u_grantor.oid, pr.type, false))
AND (pg_has_role(u_grantor.oid, 'USAGE')
OR pg_has_role(grantee.oid, 'USAGE')
***************
*** 677,683 ****
OR has_table_privilege(c.oid, 'SELECT')
OR has_table_privilege(c.oid, 'INSERT')
OR has_table_privilege(c.oid, 'UPDATE')
! OR has_table_privilege(c.oid, 'REFERENCES') );
GRANT SELECT ON columns TO PUBLIC;
--- 677,687 ----
OR has_table_privilege(c.oid, 'SELECT')
OR has_table_privilege(c.oid, 'INSERT')
OR has_table_privilege(c.oid, 'UPDATE')
! OR has_table_privilege(c.oid, 'REFERENCES')
! OR has_column_privilege(c.oid, a.attnum, 'SELECT')
! OR has_column_privilege(c.oid, a.attnum, 'INSERT')
! OR has_column_privilege(c.oid, a.attnum, 'UPDATE')
! OR has_column_privilege(c.oid, a.attnum, 'REFERENCES'));
GRANT SELECT ON columns TO PUBLIC;
Index: src/backend/catalog/system_views.sql
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/catalog/system_views.sql,v
retrieving revision 1.58
diff -c -r1.58 system_views.sql
*** src/backend/catalog/system_views.sql 1 Jan 2009 17:23:37 -0000 1.58
--- src/backend/catalog/system_views.sql 3 Feb 2009 03:17:26 -0000
***************
*** 137,143 ****
FROM pg_statistic s JOIN pg_class c ON (c.oid = s.starelid)
JOIN pg_attribute a ON (c.oid = attrelid AND attnum = s.staattnum)
LEFT JOIN pg_namespace n ON (n.oid = c.relnamespace)
! WHERE has_table_privilege(c.oid, 'select');
REVOKE ALL on pg_statistic FROM public;
--- 137,144 ----
FROM pg_statistic s JOIN pg_class c ON (c.oid = s.starelid)
JOIN pg_attribute a ON (c.oid = attrelid AND attnum = s.staattnum)
LEFT JOIN pg_namespace n ON (n.oid = c.relnamespace)
! WHERE has_table_privilege(c.oid, 'select') OR
! has_column_privilege(c.oid, a.attnum, 'select');
REVOKE ALL on pg_statistic FROM public;
Index: src/backend/commands/copy.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/commands/copy.c,v
retrieving revision 1.304
diff -c -r1.304 copy.c
*** src/backend/commands/copy.c 2 Jan 2009 20:42:00 -0000 1.304
--- src/backend/commands/copy.c 3 Feb 2009 03:17:26 -0000
***************
*** 711,717 ****
* or write to a file.
*
* Do not allow the copy if user doesn't have proper permission to access
! * the table.
*/
uint64
DoCopy(const CopyStmt *stmt, const char *queryString)
--- 711,717 ----
* or write to a file.
*
* Do not allow the copy if user doesn't have proper permission to access
! * the table or the specifically requested columns.
*/
uint64
DoCopy(const CopyStmt *stmt, const char *queryString)
***************
*** 723,729 ****
List *force_quote = NIL;
List *force_notnull = NIL;
AclMode required_access = (is_from ? ACL_INSERT : ACL_SELECT);
! AclResult aclresult;
ListCell *option;
TupleDesc tupDesc;
int num_phys_attrs;
--- 723,730 ----
List *force_quote = NIL;
List *force_notnull = NIL;
AclMode required_access = (is_from ? ACL_INSERT : ACL_SELECT);
! AclMode relPerms;
! AclMode remainingPerms;
ListCell *option;
TupleDesc tupDesc;
int num_phys_attrs;
***************
*** 973,986 ****
cstate->rel = heap_openrv(stmt->relation,
(is_from ? RowExclusiveLock : AccessShareLock));
- /* 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));
-
/* check read-only transaction */
if (XactReadOnly && is_from &&
!isTempNamespace(RelationGetNamespace(cstate->rel)))
--- 974,979 ----
***************
*** 996,1001 ****
--- 989,1021 ----
RelationGetRelationName(cstate->rel))));
tupDesc = RelationGetDescr(cstate->rel);
+
+ /* Check permissions (relation and column). */
+ relPerms = pg_class_aclmask(RelationGetRelid(cstate->rel),
+ GetUserId(),
+ required_access, ACLMASK_ALL);
+ remainingPerms = required_access & ~relPerms;
+
+ /* Check if we have column-level permissions sufficient for this
+ * operation. */
+ if (remainingPerms != 0)
+ {
+ 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));
+ }
+ }
}
else
{
Index: src/backend/utils/adt/acl.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/acl.c,v
retrieving revision 1.146
diff -c -r1.146 acl.c
*** src/backend/utils/adt/acl.c 22 Jan 2009 20:16:06 -0000 1.146
--- src/backend/utils/adt/acl.c 3 Feb 2009 03:17:26 -0000
***************
*** 1420,1425 ****
--- 1420,1904 ----
/*
+ * has_column_privilege variants
+ * These are all named "has_column_privilege" at the SQL level.
+ * They take various combinations of relation name, relation OID,
+ * column name, column attnum, user name, user OID, or
+ * implicit user = current_user.
+ *
+ * The result is a boolean value: true if user has the indicated
+ * privilege, false if not. The variants that take a relation OID
+ * return NULL if the OID doesn't exist (rather than failing, as
+ * they did before Postgres 8.4).
+ */
+
+ /*
+ * has_column_privilege_name_name_name
+ * Check user privileges on a column given
+ * name username, text tablename, text colname, and text priv name.
+ */
+ Datum
+ has_column_privilege_name_name_name(PG_FUNCTION_ARGS)
+ {
+ Name rolename = PG_GETARG_NAME(0);
+ text *tablename = PG_GETARG_TEXT_P(1);
+ text *column = PG_GETARG_TEXT_P(2);
+ text *priv_type_text = PG_GETARG_TEXT_P(3);
+ char *colname;
+ Oid roleid;
+ Oid tableoid;
+ AttrNumber colattnum;
+ AclMode mode;
+ AclResult aclresult;
+
+ roleid = get_roleid_checked(NameStr(*rolename));
+ tableoid = convert_table_name(tablename);
+
+ /* Get the number of the column */
+ colname = text_to_cstring(column);
+
+ colattnum = get_attnum(tableoid, colname);
+ if (colattnum == InvalidAttrNumber)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_COLUMN),
+ errmsg("column \"%s\" of relation \"%s\" does not exist",
+ colname, text_to_cstring(tablename))));
+
+ mode = convert_table_priv_string(priv_type_text);
+ if (mode & ~((AclMode) ACL_ALL_RIGHTS_COLUMN))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid privilege type %s for column",
+ text_to_cstring(priv_type_text))));
+
+
+ aclresult = pg_attribute_aclcheck(tableoid, colattnum, roleid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+ }
+
+ /*
+ * has_column_privilege_name_name_attnum
+ * Check user privileges on a column given
+ * name username, text tablename, int attnum, and text priv name.
+ */
+ Datum
+ has_column_privilege_name_name_attnum(PG_FUNCTION_ARGS)
+ {
+ Name rolename = PG_GETARG_NAME(0);
+ text *tablename = PG_GETARG_TEXT_P(1);
+ AttrNumber colattnum = PG_GETARG_INT16(2);
+ text *priv_type_text = PG_GETARG_TEXT_P(3);
+ Oid roleid;
+ Oid tableoid;
+ AclMode mode;
+ AclResult aclresult;
+
+ roleid = get_roleid_checked(NameStr(*rolename));
+ tableoid = convert_table_name(tablename);
+
+ mode = convert_table_priv_string(priv_type_text);
+ if (mode & ~((AclMode) ACL_ALL_RIGHTS_COLUMN))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid privilege type %s for column",
+ text_to_cstring(priv_type_text))));
+
+
+ aclresult = pg_attribute_aclcheck(tableoid, colattnum, roleid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+ }
+
+ /*
+ * has_column_privilege_name_name
+ * Check user privileges on a column given
+ * text tablename, text colname and text priv name.
+ * current_user is assumed
+ */
+ Datum
+ has_column_privilege_name_name(PG_FUNCTION_ARGS)
+ {
+ text *tablename = PG_GETARG_TEXT_P(0);
+ text *column = PG_GETARG_TEXT_P(1);
+ text *priv_type_text = PG_GETARG_TEXT_P(2);
+ char *colname;
+ AttrNumber colattnum;
+ Oid roleid;
+ Oid tableoid;
+ AclMode mode;
+ AclResult aclresult;
+
+ roleid = GetUserId();
+ tableoid = convert_table_name(tablename);
+
+ /* Get the number of the column */
+ colname = text_to_cstring(column);
+
+ colattnum = get_attnum(tableoid, colname);
+ if (colattnum == InvalidAttrNumber)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_COLUMN),
+ errmsg("column \"%s\" of relation \"%s\" does not exist",
+ colname, text_to_cstring(tablename))));
+
+ mode = convert_table_priv_string(priv_type_text);
+ if (mode & ~((AclMode) ACL_ALL_RIGHTS_COLUMN))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid privilege type %s for column",
+ text_to_cstring(priv_type_text))));
+
+ aclresult = pg_attribute_aclcheck(tableoid, colattnum, roleid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+ }
+
+ /*
+ * has_column_privilege_name_attnum
+ * Check user privileges on a column given
+ * text tablename, column attnum and text priv name.
+ * current_user is assumed
+ */
+ Datum
+ has_column_privilege_name_attnum(PG_FUNCTION_ARGS)
+ {
+ text *tablename = PG_GETARG_TEXT_P(0);
+ AttrNumber colattnum = PG_GETARG_INT16(1);
+ text *priv_type_text = PG_GETARG_TEXT_P(2);
+ Oid roleid;
+ Oid tableoid;
+ AclMode mode;
+ AclResult aclresult;
+
+ roleid = GetUserId();
+ tableoid = convert_table_name(tablename);
+
+ mode = convert_table_priv_string(priv_type_text);
+ if (mode & ~((AclMode) ACL_ALL_RIGHTS_COLUMN))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid privilege type %s for column",
+ text_to_cstring(priv_type_text))));
+
+ aclresult = pg_attribute_aclcheck(tableoid, colattnum, roleid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+ }
+
+ /*
+ * has_column_privilege_name_id_name
+ * Check user privileges on a column given
+ * name usename, table oid, text colname, and text priv name.
+ */
+ Datum
+ has_column_privilege_name_id_name(PG_FUNCTION_ARGS)
+ {
+ Name username = PG_GETARG_NAME(0);
+ Oid tableoid = PG_GETARG_OID(1);
+ text *column = PG_GETARG_TEXT_P(2);
+ text *priv_type_text = PG_GETARG_TEXT_P(3);
+ char *colname;
+ Oid roleid;
+ AttrNumber colattnum;
+ AclMode mode;
+ AclResult aclresult;
+
+ roleid = get_roleid_checked(NameStr(*username));
+
+ if (!SearchSysCacheExists(RELOID,
+ ObjectIdGetDatum(tableoid),
+ 0, 0, 0))
+ PG_RETURN_NULL();
+
+ /* Get the number of the column */
+ colname = text_to_cstring(column);
+
+ colattnum = get_attnum(tableoid, colname);
+ if (colattnum == InvalidAttrNumber)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_COLUMN),
+ errmsg("column \"%s\" of relation with OID %u does not exist",
+ colname, tableoid)));
+
+ mode = convert_table_priv_string(priv_type_text);
+ if (mode & ~((AclMode) ACL_ALL_RIGHTS_COLUMN))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid privilege type %s for column",
+ text_to_cstring(priv_type_text))));
+
+ aclresult = pg_attribute_aclcheck(tableoid, colattnum, roleid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+ }
+
+ /*
+ * has_column_privilege_name_id_attnum
+ * Check user privileges on a column given
+ * name usename, table oid, int attnum, and text priv name.
+ */
+ Datum
+ has_column_privilege_name_id_attnum(PG_FUNCTION_ARGS)
+ {
+ Name username = PG_GETARG_NAME(0);
+ Oid tableoid = PG_GETARG_OID(1);
+ AttrNumber colattnum = PG_GETARG_INT16(2);
+ text *priv_type_text = PG_GETARG_TEXT_P(3);
+ Oid roleid;
+ AclMode mode;
+ AclResult aclresult;
+
+ roleid = get_roleid_checked(NameStr(*username));
+
+ if (!SearchSysCacheExists(RELOID,
+ ObjectIdGetDatum(tableoid),
+ 0, 0, 0))
+ PG_RETURN_NULL();
+
+ mode = convert_table_priv_string(priv_type_text);
+ if (mode & ~((AclMode) ACL_ALL_RIGHTS_COLUMN))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid privilege type %s for column",
+ text_to_cstring(priv_type_text))));
+
+ aclresult = pg_attribute_aclcheck(tableoid, colattnum, roleid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+ }
+
+ /*
+ * has_column_privilege_id_name
+ * Check user privileges on a table given
+ * table oid, text column, and text priv name.
+ * current_user is assumed
+ */
+ Datum
+ has_column_privilege_id_name(PG_FUNCTION_ARGS)
+ {
+ Oid tableoid = PG_GETARG_OID(0);
+ text *column = PG_GETARG_TEXT_P(1);
+ text *priv_type_text = PG_GETARG_TEXT_P(2);
+ char *colname;
+ Oid roleid;
+ AttrNumber colattnum;
+ AclMode mode;
+ AclResult aclresult;
+
+ roleid = GetUserId();
+
+ if (!SearchSysCacheExists(RELOID,
+ ObjectIdGetDatum(tableoid),
+ 0, 0, 0))
+ PG_RETURN_NULL();
+
+ /* Get the number of the column */
+ colname = text_to_cstring(column);
+
+ colattnum = get_attnum(tableoid, colname);
+ if (colattnum == InvalidAttrNumber)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_COLUMN),
+ errmsg("column \"%s\" of relation with OID %u does not exist",
+ colname, tableoid)));
+
+ mode = convert_table_priv_string(priv_type_text);
+ if (mode & ~((AclMode) ACL_ALL_RIGHTS_COLUMN))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid privilege type %s for column",
+ text_to_cstring(priv_type_text))));
+
+ aclresult = pg_attribute_aclcheck(tableoid, colattnum, roleid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+ }
+
+ /*
+ * has_column_privilege_id_attnum
+ * Check user privileges on a table given
+ * table oid, int attnum, and text priv name.
+ * current_user is assumed
+ */
+ Datum
+ has_column_privilege_id_attnum(PG_FUNCTION_ARGS)
+ {
+ Oid tableoid = PG_GETARG_OID(0);
+ AttrNumber colattnum = PG_GETARG_INT16(1);
+ text *priv_type_text = PG_GETARG_TEXT_P(2);
+ Oid roleid;
+ AclMode mode;
+ AclResult aclresult;
+
+ roleid = GetUserId();
+
+ if (!SearchSysCacheExists(RELOID,
+ ObjectIdGetDatum(tableoid),
+ 0, 0, 0))
+ PG_RETURN_NULL();
+
+ mode = convert_table_priv_string(priv_type_text);
+ if (mode & ~((AclMode) ACL_ALL_RIGHTS_COLUMN))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid privilege type %s for column",
+ text_to_cstring(priv_type_text))));
+
+ aclresult = pg_attribute_aclcheck(tableoid, colattnum, roleid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+ }
+
+ /*
+ * has_column_privilege_id_name_name
+ * Check user privileges on a column given
+ * roleid, text tablename, text colname, and text priv name.
+ */
+ Datum
+ has_column_privilege_id_name_name(PG_FUNCTION_ARGS)
+ {
+ Oid roleid = PG_GETARG_OID(0);
+ text *tablename = PG_GETARG_TEXT_P(1);
+ text *column = PG_GETARG_TEXT_P(2);
+ text *priv_type_text = PG_GETARG_TEXT_P(3);
+ char *colname;
+ Oid tableoid;
+ AttrNumber colattnum;
+ AclMode mode;
+ AclResult aclresult;
+
+ tableoid = convert_table_name(tablename);
+
+ /* Get the number of the column */
+ colname = text_to_cstring(column);
+
+ colattnum = get_attnum(tableoid, colname);
+ if (colattnum == InvalidAttrNumber)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_COLUMN),
+ errmsg("column \"%s\" of relation \"%s\" does not exist",
+ colname, text_to_cstring(tablename))));
+
+ mode = convert_table_priv_string(priv_type_text);
+ if (mode & ~((AclMode) ACL_ALL_RIGHTS_COLUMN))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid privilege type %s for column",
+ text_to_cstring(priv_type_text))));
+
+ aclresult = pg_attribute_aclcheck(tableoid, colattnum, roleid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+ }
+
+ /*
+ * has_column_privilege_id_name_attnum
+ * Check user privileges on a column given
+ * roleid, text tablename, int attnum, and text priv name.
+ */
+ Datum
+ has_column_privilege_id_name_attnum(PG_FUNCTION_ARGS)
+ {
+ Oid roleid = PG_GETARG_OID(0);
+ text *tablename = PG_GETARG_TEXT_P(1);
+ AttrNumber colattnum = PG_GETARG_INT16(2);
+ text *priv_type_text = PG_GETARG_TEXT_P(3);
+ Oid tableoid;
+ AclMode mode;
+ AclResult aclresult;
+
+ tableoid = convert_table_name(tablename);
+
+ mode = convert_table_priv_string(priv_type_text);
+ if (mode & ~((AclMode) ACL_ALL_RIGHTS_COLUMN))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid privilege type %s for column",
+ text_to_cstring(priv_type_text))));
+
+ aclresult = pg_attribute_aclcheck(tableoid, colattnum, roleid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+ }
+
+ /*
+ * has_column_privilege_id_id_name
+ * Check user privileges on a column given
+ * roleid, table oid, text colname, and text priv name.
+ */
+ Datum
+ has_column_privilege_id_id_name(PG_FUNCTION_ARGS)
+ {
+ Oid roleid = PG_GETARG_OID(0);
+ Oid tableoid = PG_GETARG_OID(1);
+ text *column = PG_GETARG_TEXT_P(2);
+ text *priv_type_text = PG_GETARG_TEXT_P(3);
+ char *colname;
+ AttrNumber colattnum;
+ AclMode mode;
+ AclResult aclresult;
+
+ if (!SearchSysCacheExists(RELOID,
+ ObjectIdGetDatum(tableoid),
+ 0, 0, 0))
+ PG_RETURN_NULL();
+
+ /* Get the number of the column */
+ colname = text_to_cstring(column);
+
+ colattnum = get_attnum(tableoid, colname);
+ if (colattnum == InvalidAttrNumber)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_COLUMN),
+ errmsg("column \"%s\" of relation with OID %u does not exist",
+ colname, tableoid)));
+
+ mode = convert_table_priv_string(priv_type_text);
+ if (mode & ~((AclMode) ACL_ALL_RIGHTS_COLUMN))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid privilege type %s for column",
+ text_to_cstring(priv_type_text))));
+
+ aclresult = pg_attribute_aclcheck(tableoid, colattnum, roleid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+ }
+
+ /*
+ * has_column_privilege_id_id_attnum
+ * Check user privileges on a column given
+ * roleid, table oid, int colnum, and text priv name.
+ */
+ Datum
+ has_column_privilege_id_id_attnum(PG_FUNCTION_ARGS)
+ {
+ Oid roleid = PG_GETARG_OID(0);
+ Oid tableoid = PG_GETARG_OID(1);
+ AttrNumber colattnum = PG_GETARG_INT16(2);
+ text *priv_type_text = PG_GETARG_TEXT_P(3);
+ AclMode mode;
+ AclResult aclresult;
+
+ if (!SearchSysCacheExists(RELOID,
+ ObjectIdGetDatum(tableoid),
+ 0, 0, 0))
+ PG_RETURN_NULL();
+
+ mode = convert_table_priv_string(priv_type_text);
+ if (mode & ~((AclMode) ACL_ALL_RIGHTS_COLUMN))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid privilege type %s for column",
+ text_to_cstring(priv_type_text))));
+
+ aclresult = pg_attribute_aclcheck(tableoid, colattnum, roleid, mode);
+
+ PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
+ }
+
+ /*
* has_table_privilege variants
* These are all named "has_table_privilege" at the SQL level.
* They take various combinations of relation name, relation OID,
Index: src/include/catalog/pg_proc.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/catalog/pg_proc.h,v
retrieving revision 1.535
diff -c -r1.535 pg_proc.h
*** src/include/catalog/pg_proc.h 1 Jan 2009 17:23:57 -0000 1.535
--- src/include/catalog/pg_proc.h 3 Feb 2009 03:17:26 -0000
***************
*** 2913,2918 ****
--- 2913,2942 ----
DATA(insert OID = 1927 ( has_table_privilege PGNSP PGUID 12 1 0 0 f f f t f s 2 0 16 "26 25" _null_ _null_ _null_ _null_ has_table_privilege_id _null_ _null_ _null_ ));
DESCR("current user privilege on relation by rel oid");
+ DATA(insert OID = 3012 ( has_column_privilege PGNSP PGUID 12 1 0 0 f f f t f s 4 0 16 "19 25 25 25" _null_ _null_ _null_ _null_ has_column_privilege_name_name_name _null_ _null_ _null_ ));
+ DESCR("user privilege on column by username, rel name, col name");
+ DATA(insert OID = 3013 ( has_column_privilege PGNSP PGUID 12 1 0 0 f f f t f s 4 0 16 "19 25 21 25" _null_ _null_ _null_ _null_ has_column_privilege_name_name_attnum _null_ _null_ _null_ ));
+ DESCR("user privilege on column by username, rel name, col attnum");
+ DATA(insert OID = 3014 ( has_column_privilege PGNSP PGUID 12 1 0 0 f f f t f s 4 0 16 "19 26 25 25" _null_ _null_ _null_ _null_ has_column_privilege_name_id_name _null_ _null_ _null_ ));
+ DESCR("user privilege on column by username, rel oid, col name");
+ DATA(insert OID = 3015 ( has_column_privilege PGNSP PGUID 12 1 0 0 f f f t f s 4 0 16 "19 26 21 25" _null_ _null_ _null_ _null_ has_column_privilege_name_id_attnum _null_ _null_ _null_ ));
+ DESCR("user privilege on column by username, rel oid, col attnum");
+ DATA(insert OID = 3016 ( has_column_privilege PGNSP PGUID 12 1 0 0 f f f t f s 4 0 16 "26 25 25 25" _null_ _null_ _null_ _null_ has_column_privilege_id_name_name _null_ _null_ _null_ ));
+ DESCR("user privilege on column by user oid, rel name, col name");
+ DATA(insert OID = 3017 ( has_column_privilege PGNSP PGUID 12 1 0 0 f f f t f s 4 0 16 "26 25 21 25" _null_ _null_ _null_ _null_ has_column_privilege_id_name_attnum _null_ _null_ _null_ ));
+ DESCR("user privilege on column by user oid, rel name, col attnum");
+ DATA(insert OID = 3018 ( has_column_privilege PGNSP PGUID 12 1 0 0 f f f t f s 4 0 16 "26 26 25 25" _null_ _null_ _null_ _null_ has_column_privilege_id_id_name _null_ _null_ _null_ ));
+ DESCR("user privilege on column by user oid, rel oid, col name");
+ DATA(insert OID = 3019 ( has_column_privilege PGNSP PGUID 12 1 0 0 f f f t f s 4 0 16 "26 26 21 25" _null_ _null_ _null_ _null_ has_column_privilege_id_id_attnum _null_ _null_ _null_ ));
+ DESCR("user privilege on column by user oid, rel oid, col attnum");
+ DATA(insert OID = 3020 ( has_column_privilege PGNSP PGUID 12 1 0 0 f f f t f s 3 0 16 "25 25 25" _null_ _null_ _null_ _null_ has_column_privilege_name_name _null_ _null_ _null_ ));
+ DESCR("current user privilege on column by rel name, col name");
+ DATA(insert OID = 3021 ( has_column_privilege PGNSP PGUID 12 1 0 0 f f f t f s 3 0 16 "25 21 25" _null_ _null_ _null_ _null_ has_column_privilege_name_attnum _null_ _null_ _null_ ));
+ DESCR("current user privilege on column by rel name, col attnum");
+ DATA(insert OID = 3022 ( has_column_privilege PGNSP PGUID 12 1 0 0 f f f t f s 3 0 16 "26 25 25" _null_ _null_ _null_ _null_ has_column_privilege_id_name _null_ _null_ _null_ ));
+ DESCR("current user privilege on column by rel oid, col name");
+ DATA(insert OID = 3023 ( has_column_privilege PGNSP PGUID 12 1 0 0 f f f t f s 3 0 16 "26 21 25" _null_ _null_ _null_ _null_ has_column_privilege_id_attnum _null_ _null_ _null_ ));
+ DESCR("current user privilege on column by rel oid, col attnum");
DATA(insert OID = 1928 ( pg_stat_get_numscans PGNSP PGUID 12 1 0 0 f f f t f s 1 0 20 "26" _null_ _null_ _null_ _null_ pg_stat_get_numscans _null_ _null_ _null_ ));
DESCR("statistics: number of scans done for table/index");
Index: src/include/utils/builtins.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/utils/builtins.h,v
retrieving revision 1.330
diff -c -r1.330 builtins.h
*** src/include/utils/builtins.h 1 Jan 2009 17:24:02 -0000 1.330
--- src/include/utils/builtins.h 3 Feb 2009 03:17:26 -0000
***************
*** 22,27 ****
--- 22,39 ----
*/
/* acl.c */
+ extern Datum has_column_privilege_name_name_name(PG_FUNCTION_ARGS);
+ extern Datum has_column_privilege_name_name_attnum(PG_FUNCTION_ARGS);
+ extern Datum has_column_privilege_name_id_name(PG_FUNCTION_ARGS);
+ extern Datum has_column_privilege_name_id_attnum(PG_FUNCTION_ARGS);
+ extern Datum has_column_privilege_id_name_name(PG_FUNCTION_ARGS);
+ extern Datum has_column_privilege_id_name_attnum(PG_FUNCTION_ARGS);
+ extern Datum has_column_privilege_id_id_name(PG_FUNCTION_ARGS);
+ extern Datum has_column_privilege_id_id_attnum(PG_FUNCTION_ARGS);
+ extern Datum has_column_privilege_name_name(PG_FUNCTION_ARGS);
+ extern Datum has_column_privilege_name_attnum(PG_FUNCTION_ARGS);
+ extern Datum has_column_privilege_id_name(PG_FUNCTION_ARGS);
+ extern Datum has_column_privilege_id_attnum(PG_FUNCTION_ARGS);
extern Datum has_table_privilege_name_name(PG_FUNCTION_ARGS);
extern Datum has_table_privilege_name_id(PG_FUNCTION_ARGS);
extern Datum has_table_privilege_id_name(PG_FUNCTION_ARGS);
Index: src/test/regress/expected/privileges.out
===================================================================
RCS file: /projects/cvsroot/pgsql/src/test/regress/expected/privileges.out,v
retrieving revision 1.44
diff -c -r1.44 privileges.out
*** src/test/regress/expected/privileges.out 27 Jan 2009 12:40:15 -0000 1.44
--- src/test/regress/expected/privileges.out 3 Feb 2009 03:17:26 -0000
***************
*** 258,267 ****
--- 258,273 ----
1
(1 row)
+ COPY atest5 (one) TO stdout; -- ok
+ 1
SELECT two FROM atest5; -- fail
ERROR: permission denied for relation atest5
+ COPY atest5 (two) TO stdout; -- fail
+ ERROR: permission denied for relation atest5
SELECT atest5 FROM atest5; -- fail
ERROR: permission denied for relation atest5
+ COPY atest5 (one,two) TO stdout; -- fail
+ ERROR: permission denied for relation atest5
SELECT 1 FROM atest5; -- ok
?column?
----------
***************
*** 324,329 ****
--- 330,338 ----
-- test column-level privileges for INSERT and UPDATE
INSERT INTO atest5 (two) VALUES (3); -- ok
+ COPY atest5 FROM stdin; -- fail
+ ERROR: permission denied for relation atest5
+ COPY atest5 (two) FROM stdin; -- ok
INSERT INTO atest5 (three) VALUES (4); -- fail
ERROR: permission denied for relation atest5
INSERT INTO atest5 VALUES (5,5,5); -- fail
***************
*** 346,351 ****
--- 355,361 ----
--------
(0 rows)
+ COPY atest6 TO stdout; -- ok
-- test column-level privileges when involved with DELETE
SET SESSION AUTHORIZATION regressuser1;
ALTER TABLE atest6 ADD COLUMN three integer;
Index: src/test/regress/expected/rules.out
===================================================================
RCS file: /projects/cvsroot/pgsql/src/test/regress/expected/rules.out,v
retrieving revision 1.148
diff -c -r1.148 rules.out
*** src/test/regress/expected/rules.out 27 Jan 2009 12:40:15 -0000 1.148
--- src/test/regress/expected/rules.out 3 Feb 2009 03:17:26 -0000
***************
*** 1276,1283 ****
-- Check that ruleutils are working
--
SELECT viewname, definition FROM pg_views WHERE schemaname <> 'information_schema' ORDER BY viewname;
! viewname | definition
! --------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
iexit | SELECT ih.name, ih.thepath, interpt_pp(ih.thepath, r.thepath) AS exit FROM ihighway ih, ramp r WHERE (ih.thepath ## r.thepath);
pg_cursors | SELECT c.name, c.statement, c.is_holdable, c.is_binary, c.is_scrollable, c.creation_time FROM pg_cursor() c(name, statement, is_holdable, is_binary, is_scrollable, creation_time);
pg_group | SELECT pg_authid.rolname AS groname, pg_authid.oid AS grosysid, ARRAY(SELECT pg_auth_members.member FROM pg_auth_members WHERE (pg_auth_members.roleid = pg_authid.oid)) AS grolist FROM pg_authid WHERE (NOT pg_authid.rolcanlogin);
--- 1276,1283 ----
-- Check that ruleutils are working
--
SELECT viewname, definition FROM pg_views WHERE schemaname <> 'information_schema' ORDER BY viewname;
! viewname | definition
! --------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
iexit | SELECT ih.name, ih.thepath, interpt_pp(ih.thepath, r.thepath) AS exit FROM ihighway ih, ramp r WHERE (ih.thepath ## r.thepath);
pg_cursors | SELECT c.name, c.statement, c.is_holdable, c.is_binary, c.is_scrollable, c.creation_time FROM pg_cursor() c(name, statement, is_holdable, is_binary, is_scrollable, creation_time);
pg_group | SELECT pg_authid.rolname AS groname, pg_authid.oid AS grosysid, ARRAY(SELECT pg_auth_members.member FROM pg_auth_members WHERE (pg_auth_members.roleid = pg_authid.oid)) AS grolist FROM pg_authid WHERE (NOT pg_authid.rolcanlogin);
***************
*** 1308,1314 ****
pg_statio_user_indexes | SELECT pg_statio_all_indexes.relid, pg_statio_all_indexes.indexrelid, pg_statio_all_indexes.schemaname, pg_statio_all_indexes.relname, pg_statio_all_indexes.indexrelname, pg_statio_all_indexes.idx_blks_read, pg_statio_all_indexes.idx_blks_hit FROM pg_statio_all_indexes WHERE ((pg_statio_all_indexes.schemaname <> ALL (ARRAY['pg_catalog'::name, 'information_schema'::name])) AND (pg_statio_all_indexes.schemaname !~ '^pg_toast'::text));
pg_statio_user_sequences | SELECT pg_statio_all_sequences.relid, pg_statio_all_sequences.schemaname, pg_statio_all_sequences.relname, pg_statio_all_sequences.blks_read, pg_statio_all_sequences.blks_hit FROM pg_statio_all_sequences WHERE ((pg_statio_all_sequences.schemaname <> ALL (ARRAY['pg_catalog'::name, 'information_schema'::name])) AND (pg_statio_all_sequences.schemaname !~ '^pg_toast'::text));
pg_statio_user_tables | SELECT pg_statio_all_tables.relid, pg_statio_all_tables.schemaname, pg_statio_all_tables.relname, pg_statio_all_tables.heap_blks_read, pg_statio_all_tables.heap_blks_hit, pg_statio_all_tables.idx_blks_read, pg_statio_all_tables.idx_blks_hit, pg_statio_all_tables.toast_blks_read, pg_statio_all_tables.toast_blks_hit, pg_statio_all_tables.tidx_blks_read, pg_statio_all_tables.tidx_blks_hit FROM pg_statio_all_tables WHERE ((pg_statio_all_tables.schemaname <> ALL (ARRAY['pg_catalog'::name, 'information_schema'::name])) AND (pg_statio_all_tables.schemaname !~ '^pg_toast'::text));
! pg_stats | SELECT n.nspname AS schemaname, c.relname AS tablename, a.attname, s.stanullfrac AS null_frac, s.stawidth AS avg_width, s.stadistinct AS n_distinct, CASE WHEN (s.stakind1 = ANY (ARRAY[1, 4])) THEN s.stavalues1 WHEN (s.stakind2 = ANY (ARRAY[1, 4])) THEN s.stavalues2 WHEN (s.stakind3 = ANY (ARRAY[1, 4])) THEN s.stavalues3 WHEN (s.stakind4 = ANY (ARRAY[1, 4])) THEN s.stavalues4 ELSE NULL::anyarray END AS most_common_vals, CASE WHEN (s.stakind1 = ANY (ARRAY[1, 4])) THEN s.stanumbers1 WHEN (s.stakind2 = ANY (ARRAY[1, 4])) THEN s.stanumbers2 WHEN (s.stakind3 = ANY (ARRAY[1, 4])) THEN s.stanumbers3 WHEN (s.stakind4 = ANY (ARRAY[1, 4])) THEN s.stanumbers4 ELSE NULL::real[] END AS most_common_freqs, CASE WHEN (s.stakind1 = 2) THEN s.stavalues1 WHEN (s.stakind2 = 2) THEN s.stavalues2 WHEN (s.stakind3 = 2) THEN s.stavalues3 WHEN (s.stakind4 = 2) THEN s.stavalues4 ELSE NULL::anyarray END AS histogram_bounds, CASE WHEN (s.stakind1 = 3) THEN s.stanumbers1[1] WHEN (s.stakind2 = 3) THEN s.stanumbers2[1] WHEN (s.stakind3 = 3) THEN s.stanumbers3[1] WHEN (s.stakind4 = 3) THEN s.stanumbers4[1] ELSE NULL::real END AS correlation FROM (((pg_statistic s JOIN pg_class c ON ((c.oid = s.starelid))) JOIN pg_attribute a ON (((c.oid = a.attrelid) AND (a.attnum = s.staattnum)))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE has_table_privilege(c.oid, 'select'::text);
pg_tables | SELECT n.nspname AS schemaname, c.relname AS tablename, pg_get_userbyid(c.relowner) AS tableowner, t.spcname AS tablespace, c.relhasindex AS hasindexes, c.relhasrules AS hasrules, c.relhastriggers AS hastriggers FROM ((pg_class c LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) LEFT JOIN pg_tablespace t ON ((t.oid = c.reltablespace))) WHERE (c.relkind = 'r'::"char");
pg_timezone_abbrevs | SELECT pg_timezone_abbrevs.abbrev, pg_timezone_abbrevs.utc_offset, pg_timezone_abbrevs.is_dst FROM pg_timezone_abbrevs() pg_timezone_abbrevs(abbrev, utc_offset, is_dst);
pg_timezone_names | SELECT pg_timezone_names.name, pg_timezone_names.abbrev, pg_timezone_names.utc_offset, pg_timezone_names.is_dst FROM pg_timezone_names() pg_timezone_names(name, abbrev, utc_offset, is_dst);
--- 1308,1314 ----
pg_statio_user_indexes | SELECT pg_statio_all_indexes.relid, pg_statio_all_indexes.indexrelid, pg_statio_all_indexes.schemaname, pg_statio_all_indexes.relname, pg_statio_all_indexes.indexrelname, pg_statio_all_indexes.idx_blks_read, pg_statio_all_indexes.idx_blks_hit FROM pg_statio_all_indexes WHERE ((pg_statio_all_indexes.schemaname <> ALL (ARRAY['pg_catalog'::name, 'information_schema'::name])) AND (pg_statio_all_indexes.schemaname !~ '^pg_toast'::text));
pg_statio_user_sequences | SELECT pg_statio_all_sequences.relid, pg_statio_all_sequences.schemaname, pg_statio_all_sequences.relname, pg_statio_all_sequences.blks_read, pg_statio_all_sequences.blks_hit FROM pg_statio_all_sequences WHERE ((pg_statio_all_sequences.schemaname <> ALL (ARRAY['pg_catalog'::name, 'information_schema'::name])) AND (pg_statio_all_sequences.schemaname !~ '^pg_toast'::text));
pg_statio_user_tables | SELECT pg_statio_all_tables.relid, pg_statio_all_tables.schemaname, pg_statio_all_tables.relname, pg_statio_all_tables.heap_blks_read, pg_statio_all_tables.heap_blks_hit, pg_statio_all_tables.idx_blks_read, pg_statio_all_tables.idx_blks_hit, pg_statio_all_tables.toast_blks_read, pg_statio_all_tables.toast_blks_hit, pg_statio_all_tables.tidx_blks_read, pg_statio_all_tables.tidx_blks_hit FROM pg_statio_all_tables WHERE ((pg_statio_all_tables.schemaname <> ALL (ARRAY['pg_catalog'::name, 'information_schema'::name])) AND (pg_statio_all_tables.schemaname !~ '^pg_toast'::text));
! pg_stats | SELECT n.nspname AS schemaname, c.relname AS tablename, a.attname, s.stanullfrac AS null_frac, s.stawidth AS avg_width, s.stadistinct AS n_distinct, CASE WHEN (s.stakind1 = ANY (ARRAY[1, 4])) THEN s.stavalues1 WHEN (s.stakind2 = ANY (ARRAY[1, 4])) THEN s.stavalues2 WHEN (s.stakind3 = ANY (ARRAY[1, 4])) THEN s.stavalues3 WHEN (s.stakind4 = ANY (ARRAY[1, 4])) THEN s.stavalues4 ELSE NULL::anyarray END AS most_common_vals, CASE WHEN (s.stakind1 = ANY (ARRAY[1, 4])) THEN s.stanumbers1 WHEN (s.stakind2 = ANY (ARRAY[1, 4])) THEN s.stanumbers2 WHEN (s.stakind3 = ANY (ARRAY[1, 4])) THEN s.stanumbers3 WHEN (s.stakind4 = ANY (ARRAY[1, 4])) THEN s.stanumbers4 ELSE NULL::real[] END AS most_common_freqs, CASE WHEN (s.stakind1 = 2) THEN s.stavalues1 WHEN (s.stakind2 = 2) THEN s.stavalues2 WHEN (s.stakind3 = 2) THEN s.stavalues3 WHEN (s.stakind4 = 2) THEN s.stavalues4 ELSE NULL::anyarray END AS histogram_bounds, CASE WHEN (s.stakind1 = 3) THEN s.stanumbers1[1] WHEN (s.stakind2 = 3) THEN s.stanumbers2[1] WHEN (s.stakind3 = 3) THEN s.stanumbers3[1] WHEN (s.stakind4 = 3) THEN s.stanumbers4[1] ELSE NULL::real END AS correlation FROM (((pg_statistic s JOIN pg_class c ON ((c.oid = s.starelid))) JOIN pg_attribute a ON (((c.oid = a.attrelid) AND (a.attnum = s.staattnum)))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (has_table_privilege(c.oid, 'select'::text) OR has_column_privilege(c.oid, a.attnum, 'select'::text));
pg_tables | SELECT n.nspname AS schemaname, c.relname AS tablename, pg_get_userbyid(c.relowner) AS tableowner, t.spcname AS tablespace, c.relhasindex AS hasindexes, c.relhasrules AS hasrules, c.relhastriggers AS hastriggers FROM ((pg_class c LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) LEFT JOIN pg_tablespace t ON ((t.oid = c.reltablespace))) WHERE (c.relkind = 'r'::"char");
pg_timezone_abbrevs | SELECT pg_timezone_abbrevs.abbrev, pg_timezone_abbrevs.utc_offset, pg_timezone_abbrevs.is_dst FROM pg_timezone_abbrevs() pg_timezone_abbrevs(abbrev, utc_offset, is_dst);
pg_timezone_names | SELECT pg_timezone_names.name, pg_timezone_names.abbrev, pg_timezone_names.utc_offset, pg_timezone_names.is_dst FROM pg_timezone_names() pg_timezone_names(name, abbrev, utc_offset, is_dst);
Index: src/test/regress/sql/privileges.sql
===================================================================
RCS file: /projects/cvsroot/pgsql/src/test/regress/sql/privileges.sql,v
retrieving revision 1.23
diff -c -r1.23 privileges.sql
*** src/test/regress/sql/privileges.sql 22 Jan 2009 20:16:10 -0000 1.23
--- src/test/regress/sql/privileges.sql 3 Feb 2009 03:17:26 -0000
***************
*** 184,191 ****
--- 184,194 ----
SET SESSION AUTHORIZATION regressuser4;
SELECT * FROM atest5; -- fail
SELECT one FROM atest5; -- ok
+ COPY atest5 (one) TO stdout; -- ok
SELECT two FROM atest5; -- fail
+ COPY atest5 (two) TO stdout; -- fail
SELECT atest5 FROM atest5; -- fail
+ COPY atest5 (one,two) TO stdout; -- fail
SELECT 1 FROM atest5; -- ok
SELECT 1 FROM atest5 a JOIN atest5 b USING (one); -- ok
SELECT 1 FROM atest5 a JOIN atest5 b USING (two); -- fail
***************
*** 213,218 ****
--- 216,225 ----
-- test column-level privileges for INSERT and UPDATE
INSERT INTO atest5 (two) VALUES (3); -- ok
+ COPY atest5 FROM stdin; -- fail
+ COPY atest5 (two) FROM stdin; -- ok
+ 1
+ \.
INSERT INTO atest5 (three) VALUES (4); -- fail
INSERT INTO atest5 VALUES (5,5,5); -- fail
UPDATE atest5 SET three = 10; -- ok
***************
*** 227,232 ****
--- 234,240 ----
SELECT one FROM atest5; -- fail
UPDATE atest5 SET one = 1; -- fail
SELECT atest6 FROM atest6; -- ok
+ COPY atest6 TO stdout; -- ok
-- test column-level privileges when involved with DELETE
SET SESSION AUTHORIZATION regressuser1;
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers