Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 7ceed2a

Browse files
committed
Allow GRANT/REVOKE to/from more than one user per invocation. Command tag
for GRANT/REVOKE is now just that, not "CHANGE". On the way, migrate some of the aclitem internal representation away from the parser and build a real parse tree instead. Also add some 'const' qualifiers.
1 parent 202548d commit 7ceed2a

File tree

14 files changed

+269
-203
lines changed

14 files changed

+269
-203
lines changed

doc/src/sgml/ref/grant.sgml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$Header: /cvsroot/pgsql/doc/src/sgml/ref/grant.sgml,v 1.10 2001/05/27 09:59:28 petere Exp $
2+
$Header: /cvsroot/pgsql/doc/src/sgml/ref/grant.sgml,v 1.11 2001/06/09 23:21:54 petere Exp $
33
Postgres documentation
44
-->
55

@@ -18,7 +18,7 @@ Postgres documentation
1818
<synopsis>
1919
GRANT { { SELECT | INSERT | UPDATE | DELETE | RULE | REFERENCES | TRIGGER } [,...] | ALL [ PRIVILEGES ] }
2020
ON [ TABLE ] <replaceable class="PARAMETER">objectname</replaceable> [, ...]
21-
TO { <replaceable class="PARAMETER">username</replaceable> | GROUP <replaceable class="PARAMETER">groupname</replaceable> | PUBLIC }
21+
TO { <replaceable class="PARAMETER">username</replaceable> | GROUP <replaceable class="PARAMETER">groupname</replaceable> | PUBLIC } [, ...]
2222
</synopsis>
2323
</refsynopsisdiv>
2424

doc/src/sgml/ref/revoke.sgml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$Header: /cvsroot/pgsql/doc/src/sgml/ref/revoke.sgml,v 1.14 2001/05/27 09:59:28 petere Exp $
2+
$Header: /cvsroot/pgsql/doc/src/sgml/ref/revoke.sgml,v 1.15 2001/06/09 23:21:54 petere Exp $
33
Postgres documentation
44
-->
55

@@ -18,7 +18,7 @@ Postgres documentation
1818
<synopsis>
1919
REVOKE { { SELECT | INSERT | UPDATE | DELETE | RULE | REFERENCES | TRIGGER } [,...] | ALL [ PRIVILEGES ] }
2020
ON [ TABLE ] <replaceable class="PARAMETER">object</replaceable> [, ...]
21-
FROM { <replaceable class="PARAMETER">username</replaceable> | GROUP <replaceable class="PARAMETER">groupname</replaceable> | PUBLIC }
21+
FROM { <replaceable class="PARAMETER">username</replaceable> | GROUP <replaceable class="PARAMETER">groupname</replaceable> | PUBLIC } [, ...]
2222
</synopsis>
2323
</refsynopsisdiv>
2424

src/backend/catalog/aclchk.c

Lines changed: 106 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.49 2001/06/05 19:34:56 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.50 2001/06/09 23:21:54 petere Exp $
1212
*
1313
* NOTES
1414
* See acl.h.
@@ -63,95 +63,132 @@ dumpacl(Acl *acl)
6363

6464
#endif /* ACLDEBUG */
6565

66+
6667
/*
67-
* ChangeAcl
68+
* Called to execute the utility commands GRANT and REVOKE
6869
*/
6970
void
70-
ChangeAcl(char *relname,
71-
AclItem *mod_aip,
72-
unsigned modechg)
71+
ExecuteGrantStmt(GrantStmt *stmt)
7372
{
74-
unsigned i;
75-
Acl *old_acl,
76-
*new_acl;
77-
Relation relation;
78-
HeapTuple tuple;
79-
HeapTuple newtuple;
80-
Datum aclDatum;
81-
Datum values[Natts_pg_class];
82-
char nulls[Natts_pg_class];
83-
char replaces[Natts_pg_class];
84-
Relation idescs[Num_pg_class_indices];
85-
bool isNull;
73+
List *i;
74+
List *j;
8675

87-
/*
88-
* Find the pg_class tuple matching 'relname' and extract the ACL. If
89-
* there's no ACL, create a default using the pg_class.relowner field.
90-
*/
91-
relation = heap_openr(RelationRelationName, RowExclusiveLock);
92-
tuple = SearchSysCache(RELNAME,
93-
PointerGetDatum(relname),
94-
0, 0, 0);
95-
if (!HeapTupleIsValid(tuple))
96-
{
97-
heap_close(relation, RowExclusiveLock);
98-
elog(ERROR, "ChangeAcl: class \"%s\" not found",
99-
relname);
100-
}
101-
102-
aclDatum = SysCacheGetAttr(RELNAME, tuple, Anum_pg_class_relacl,
103-
&isNull);
104-
if (isNull)
105-
{
106-
/* No ACL, so build default ACL for rel */
107-
AclId ownerId;
76+
/* see comment in pg_type.h */
77+
Assert(ACLITEMSIZE == sizeof(AclItem));
10878

109-
ownerId = ((Form_pg_class) GETSTRUCT(tuple))->relowner;
110-
old_acl = acldefault(relname, ownerId);
111-
}
112-
else
79+
foreach(i, stmt->relnames)
11380
{
114-
/* get a detoasted copy of the rel's ACL */
115-
old_acl = DatumGetAclPCopy(aclDatum);
116-
}
81+
char *relname = strVal(lfirst(i));
82+
Relation relation;
83+
HeapTuple tuple;
84+
Form_pg_class pg_class_tuple;
85+
Datum aclDatum;
86+
bool isNull;
87+
Acl *old_acl;
88+
Acl *new_acl;
89+
unsigned i;
90+
HeapTuple newtuple;
91+
Datum values[Natts_pg_class];
92+
char nulls[Natts_pg_class];
93+
char replaces[Natts_pg_class];
94+
95+
96+
if (!pg_ownercheck(GetUserId(), relname, RELNAME))
97+
elog(ERROR, "permission denied");
98+
99+
/* open pg_class */
100+
relation = heap_openr(RelationRelationName, RowExclusiveLock);
101+
tuple = SearchSysCache(RELNAME,
102+
PointerGetDatum(relname),
103+
0, 0, 0);
104+
if (!HeapTupleIsValid(tuple))
105+
{
106+
heap_close(relation, RowExclusiveLock);
107+
elog(ERROR, "relation \"%s\" not found",
108+
relname);
109+
}
110+
pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
111+
112+
if (pg_class_tuple->relkind == RELKIND_INDEX)
113+
elog(ERROR, "\"%s\" is an index",
114+
relname);
115+
116+
/*
117+
* If there's no ACL, create a default using the
118+
* pg_class.relowner field.
119+
*/
120+
aclDatum = SysCacheGetAttr(RELNAME, tuple, Anum_pg_class_relacl,
121+
&isNull);
122+
if (isNull)
123+
old_acl = acldefault(relname, pg_class_tuple->relowner);
124+
else
125+
/* get a detoasted copy of the rel's ACL */
126+
old_acl = DatumGetAclPCopy(aclDatum);
117127

118128
#ifdef ACLDEBUG
119-
dumpacl(old_acl);
129+
dumpacl(old_acl);
120130
#endif
131+
new_acl = old_acl;
121132

122-
new_acl = aclinsert3(old_acl, mod_aip, modechg);
123-
133+
foreach(j, stmt->grantees)
134+
{
135+
PrivGrantee *grantee = (PrivGrantee *)lfirst(j);
136+
char *granteeString;
137+
char *aclString;
138+
AclItem aclitem;
139+
unsigned modechg;
140+
141+
if (grantee->username)
142+
granteeString = aclmakeuser("U", grantee->username);
143+
else if (grantee->groupname)
144+
granteeString = aclmakeuser("G", grantee->groupname);
145+
else
146+
granteeString = aclmakeuser("A", "");
147+
148+
aclString = makeAclString(stmt->privileges, granteeString,
149+
stmt->is_grant ? '+' : '-');
150+
151+
/* Convert string ACL spec into internal form */
152+
aclparse(aclString, &aclitem, &modechg);
153+
new_acl = aclinsert3(new_acl, &aclitem, modechg);
124154
#ifdef ACLDEBUG
125-
dumpacl(new_acl);
155+
dumpacl(new_acl);
126156
#endif
157+
}
127158

128-
for (i = 0; i < Natts_pg_class; ++i)
129-
{
130-
replaces[i] = ' ';
131-
nulls[i] = ' '; /* ignored if replaces[i] == ' ' anyway */
132-
values[i] = (Datum) NULL; /* ignored if replaces[i] == ' '
133-
* anyway */
134-
}
135-
replaces[Anum_pg_class_relacl - 1] = 'r';
136-
values[Anum_pg_class_relacl - 1] = PointerGetDatum(new_acl);
137-
newtuple = heap_modifytuple(tuple, relation, values, nulls, replaces);
159+
/* finished building new ACL value, now insert it */
160+
for (i = 0; i < Natts_pg_class; ++i)
161+
{
162+
replaces[i] = ' ';
163+
nulls[i] = ' '; /* ignored if replaces[i]==' ' anyway */
164+
values[i] = (Datum) NULL; /* ignored if replaces[i]==' ' anyway */
165+
}
166+
replaces[Anum_pg_class_relacl - 1] = 'r';
167+
values[Anum_pg_class_relacl - 1] = PointerGetDatum(new_acl);
168+
newtuple = heap_modifytuple(tuple, relation, values, nulls, replaces);
138169

139-
ReleaseSysCache(tuple);
170+
ReleaseSysCache(tuple);
140171

141-
simple_heap_update(relation, &newtuple->t_self, newtuple);
172+
simple_heap_update(relation, &newtuple->t_self, newtuple);
142173

143-
/* keep the catalog indices up to date */
144-
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices,
145-
idescs);
146-
CatalogIndexInsert(idescs, Num_pg_class_indices, relation, newtuple);
147-
CatalogCloseIndices(Num_pg_class_indices, idescs);
174+
{
175+
/* keep the catalog indexes up to date */
176+
Relation idescs[Num_pg_class_indices];
177+
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices,
178+
idescs);
179+
CatalogIndexInsert(idescs, Num_pg_class_indices, relation, newtuple);
180+
CatalogCloseIndices(Num_pg_class_indices, idescs);
181+
}
148182

149-
heap_close(relation, RowExclusiveLock);
183+
pfree(old_acl);
184+
pfree(new_acl);
150185

151-
pfree(old_acl);
152-
pfree(new_acl);
186+
heap_close(relation, RowExclusiveLock);
187+
}
153188
}
154189

190+
191+
155192
AclId
156193
get_grosysid(char *groname)
157194
{

src/backend/nodes/copyfuncs.c

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* Portions Copyright (c) 1994, Regents of the University of California
1616
*
1717
* IDENTIFICATION
18-
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.143 2001/06/05 05:26:03 tgl Exp $
18+
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.144 2001/06/09 23:21:54 petere Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -24,7 +24,6 @@
2424

2525
#include "optimizer/clauses.h"
2626
#include "optimizer/planmain.h"
27-
#include "utils/acl.h"
2827

2928

3029
/*
@@ -1856,14 +1855,29 @@ _copyAlterTableStmt(AlterTableStmt *from)
18561855
return newnode;
18571856
}
18581857

1859-
static ChangeACLStmt *
1860-
_copyChangeACLStmt(ChangeACLStmt *from)
1858+
static GrantStmt *
1859+
_copyGrantStmt(GrantStmt *from)
18611860
{
1862-
ChangeACLStmt *newnode = makeNode(ChangeACLStmt);
1861+
GrantStmt *newnode = makeNode(GrantStmt);
18631862

1864-
Node_Copy(from, newnode, relNames);
1865-
if (from->aclString)
1866-
newnode->aclString = pstrdup(from->aclString);
1863+
newnode->is_grant = from->is_grant;
1864+
Node_Copy(from, newnode, relnames);
1865+
if (from->privileges)
1866+
newnode->privileges = pstrdup(from->privileges);
1867+
Node_Copy(from, newnode, grantees);
1868+
1869+
return newnode;
1870+
}
1871+
1872+
static PrivGrantee *
1873+
_copyPrivGrantee(PrivGrantee *from)
1874+
{
1875+
PrivGrantee *newnode = makeNode(PrivGrantee);
1876+
1877+
if (from->username)
1878+
newnode->username = pstrdup(from->username);
1879+
if (from->groupname)
1880+
newnode->groupname = pstrdup(from->groupname);
18671881

18681882
return newnode;
18691883
}
@@ -2729,8 +2743,8 @@ copyObject(void *from)
27292743
case T_AlterTableStmt:
27302744
retval = _copyAlterTableStmt(from);
27312745
break;
2732-
case T_ChangeACLStmt:
2733-
retval = _copyChangeACLStmt(from);
2746+
case T_GrantStmt:
2747+
retval = _copyGrantStmt(from);
27342748
break;
27352749
case T_ClosePortalStmt:
27362750
retval = _copyClosePortalStmt(from);
@@ -2943,6 +2957,9 @@ copyObject(void *from)
29432957
case T_FkConstraint:
29442958
retval = _copyFkConstraint(from);
29452959
break;
2960+
case T_PrivGrantee:
2961+
retval = _copyPrivGrantee(from);
2962+
break;
29462963

29472964
default:
29482965
elog(ERROR, "copyObject: don't know how to copy node type %d",

src/backend/nodes/equalfuncs.c

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
* Portions Copyright (c) 1994, Regents of the University of California
2121
*
2222
* IDENTIFICATION
23-
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.91 2001/06/05 05:26:03 tgl Exp $
23+
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.92 2001/06/09 23:21:54 petere Exp $
2424
*
2525
*-------------------------------------------------------------------------
2626
*/
@@ -29,7 +29,6 @@
2929

3030
#include "nodes/plannodes.h"
3131
#include "nodes/relation.h"
32-
#include "utils/acl.h"
3332
#include "utils/datum.h"
3433

3534

@@ -755,16 +754,27 @@ _equalAlterTableStmt(AlterTableStmt *a, AlterTableStmt *b)
755754
}
756755

757756
static bool
758-
_equalChangeACLStmt(ChangeACLStmt *a, ChangeACLStmt *b)
757+
_equalGrantStmt(GrantStmt *a, GrantStmt *b)
759758
{
760-
if (!equal(a->relNames, b->relNames))
759+
if (a->is_grant != b->is_grant)
761760
return false;
762-
if (!equalstr(a->aclString, b->aclString))
761+
if (!equal(a->relnames, b->relnames))
762+
return false;
763+
if (!equalstr(a->privileges, b->privileges))
764+
return false;
765+
if (!equal(a->grantees, b->grantees))
763766
return false;
764767

765768
return true;
766769
}
767770

771+
static bool
772+
_equalPrivGrantee(PrivGrantee *a, PrivGrantee *b)
773+
{
774+
return equalstr(a->username, b->username)
775+
&& equalstr(a->groupname, b->groupname);
776+
}
777+
768778
static bool
769779
_equalClosePortalStmt(ClosePortalStmt *a, ClosePortalStmt *b)
770780
{
@@ -1898,8 +1908,8 @@ equal(void *a, void *b)
18981908
case T_AlterTableStmt:
18991909
retval = _equalAlterTableStmt(a, b);
19001910
break;
1901-
case T_ChangeACLStmt:
1902-
retval = _equalChangeACLStmt(a, b);
1911+
case T_GrantStmt:
1912+
retval = _equalGrantStmt(a, b);
19031913
break;
19041914
case T_ClosePortalStmt:
19051915
retval = _equalClosePortalStmt(a, b);
@@ -2113,6 +2123,9 @@ equal(void *a, void *b)
21132123
case T_FkConstraint:
21142124
retval = _equalFkConstraint(a, b);
21152125
break;
2126+
case T_PrivGrantee:
2127+
retval = _equalPrivGrantee(a, b);
2128+
break;
21162129

21172130
default:
21182131
elog(NOTICE, "equal: don't know whether nodes of type %d are equal",

0 commit comments

Comments
 (0)