diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c index 482bb924dcb4320e06c66002cf7087f1e3da876d..bab118573037a667be0b1c751f78727b7752b95b 100644 --- a/src/backend/access/heap/tuptoaster.c +++ b/src/backend/access/heap/tuptoaster.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.9 2000/07/22 11:18:46 wieck Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.10 2000/07/31 22:39:17 tgl Exp $ * * * INTERFACE ROUTINES @@ -273,7 +273,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup) /* ---------- * If the old value is an external stored one, check if it - * has changed so we have to detele it later. + * has changed so we have to delete it later. * ---------- */ if (!old_isnull && att[i]->attlen == -1 && @@ -336,17 +336,16 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup) if (att[i]->attlen == -1) { /* ---------- - * If the tables attribute say's PLAIN allways, we - * do so below. + * If the table's attribute says PLAIN always, force it so. * ---------- */ if (att[i]->attstorage == 'p') toast_action[i] = 'p'; /* ---------- - * We're running for UPDATE, so any TOASTed value we find - * still in the tuple must be someone elses we cannot reuse. - * Expand it to plain and eventually toast it again below. + * We took care of UPDATE above, so any TOASTed value we find + * still in the tuple must be someone else's we cannot reuse. + * Expand it to plain (and, probably, toast it again below). * ---------- */ if (VARATT_IS_EXTENDED(DatumGetPointer(toast_values[i]))) @@ -367,7 +366,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup) else { /* ---------- - * Not a variable size attribute, plain storage allways + * Not a variable size attribute, plain storage always * ---------- */ toast_action[i] = 'p'; diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index c342b067ff4078b610db7eae0eb8197d6d8894b7..6be489a0c74eb7a5650f15f988aa33c22c56a0eb 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.38 2000/04/12 17:14:55 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.39 2000/07/31 22:39:13 tgl Exp $ * * NOTES * See acl.h. @@ -33,7 +33,8 @@ #include "utils/acl.h" #include "utils/syscache.h" -static int32 aclcheck(char *relname, Acl *acl, AclId id, AclIdType idtype, AclMode mode); +static int32 aclcheck(char *relname, Acl *acl, AclId id, + AclIdType idtype, AclMode mode); /* * Enable use of user relations in place of real system catalogs. @@ -68,14 +69,16 @@ char *aclcheck_error_strings[] = { static dumpacl(Acl *acl) { - unsigned i; + int i; AclItem *aip; elog(DEBUG, "acl size = %d, # acls = %d", ACL_SIZE(acl), ACL_NUM(acl)); - aip = (AclItem *) ACL_DAT(acl); + aip = ACL_DAT(acl); for (i = 0; i < ACL_NUM(acl); ++i) - elog(DEBUG, " acl[%d]: %s", i, aclitemout(aip + i)); + elog(DEBUG, " acl[%d]: %s", i, + DatumGetCString(DirectFunctionCall1(aclitemout, + PointerGetDatum(aip + i)))); } #endif @@ -89,7 +92,7 @@ ChangeAcl(char *relname, unsigned modechg) { unsigned i; - Acl *old_acl = (Acl *) NULL, + Acl *old_acl, *new_acl; Relation relation; HeapTuple tuple; @@ -97,14 +100,12 @@ ChangeAcl(char *relname, char nulls[Natts_pg_class]; char replaces[Natts_pg_class]; Relation idescs[Num_pg_class_indices]; - int free_old_acl = 0; + bool isNull; + bool free_old_acl = false; /* * Find the pg_class tuple matching 'relname' and extract the ACL. If * there's no ACL, create a default using the pg_class.relowner field. - * - * We can't use the syscache here, since we need to do a heap_update on - * the tuple we find. */ relation = heap_openr(RelationRelationName, RowExclusiveLock); tuple = SearchSysCacheTuple(RELNAME, @@ -117,25 +118,37 @@ ChangeAcl(char *relname, relname); } - if (!heap_attisnull(tuple, Anum_pg_class_relacl)) - old_acl = (Acl *) heap_getattr(tuple, - Anum_pg_class_relacl, - RelationGetDescr(relation), - (bool *) NULL); - if (!old_acl || ACL_NUM(old_acl) < 1) + old_acl = (Acl *) heap_getattr(tuple, + Anum_pg_class_relacl, + RelationGetDescr(relation), + &isNull); + if (isNull) { #ifdef ACLDEBUG_TRACE elog(DEBUG, "ChangeAcl: using default ACL"); #endif -/* old_acl = acldefault(((Form_pg_class) GETSTRUCT(tuple))->relowner); */ old_acl = acldefault(relname); - free_old_acl = 1; + free_old_acl = true; + } + + /* Need to detoast the old ACL for modification */ + old_acl = DatumGetAclP(PointerGetDatum(old_acl)); + + if (ACL_NUM(old_acl) < 1) + { +#ifdef ACLDEBUG_TRACE + elog(DEBUG, "ChangeAcl: old ACL has zero length"); +#endif + old_acl = acldefault(relname); + free_old_acl = true; } #ifdef ACLDEBUG_TRACE dumpacl(old_acl); #endif + new_acl = aclinsert3(old_acl, mod_aip, modechg); + #ifdef ACLDEBUG_TRACE dumpacl(new_acl); #endif @@ -148,7 +161,7 @@ ChangeAcl(char *relname, * anyway */ } replaces[Anum_pg_class_relacl - 1] = 'r'; - values[Anum_pg_class_relacl - 1] = (Datum) new_acl; + values[Anum_pg_class_relacl - 1] = PointerGetDatum(new_acl); tuple = heap_modifytuple(tuple, relation, values, nulls, replaces); heap_update(relation, &tuple->t_self, tuple, NULL); @@ -193,20 +206,20 @@ get_groname(AclId grosysid) if (HeapTupleIsValid(tuple)) name = NameStr(((Form_pg_group) GETSTRUCT(tuple))->groname); else - elog(NOTICE, "get_groname: group %d not found", grosysid); + elog(NOTICE, "get_groname: group %u not found", grosysid); return name; } -static int32 +static bool in_group(AclId uid, AclId gid) { Relation relation; HeapTuple tuple; Acl *tmp; - unsigned i, + int i, num; AclId *aidp; - int32 found = 0; + bool found = false; relation = heap_openr(GroupRelationName, RowExclusiveLock); tuple = SearchSysCacheTuple(GROSYSID, @@ -219,13 +232,15 @@ in_group(AclId uid, AclId gid) Anum_pg_group_grolist, RelationGetDescr(relation), (bool *) NULL); + /* be sure the IdList is not toasted */ + tmp = DatumGetIdListP(PointerGetDatum(tmp)); /* XXX make me a function */ num = IDLIST_NUM(tmp); aidp = IDLIST_DAT(tmp); for (i = 0; i < num; ++i) if (aidp[i] == uid) { - found = 1; + found = true; break; } } @@ -344,8 +359,7 @@ pg_aclcheck(char *relname, char *usename, AclMode mode) { HeapTuple tuple; AclId id; - Acl *acl = (Acl *) NULL, - *tmp; + Acl *acl = (Acl *) NULL; int32 result; Relation relation; @@ -396,12 +410,11 @@ pg_aclcheck(char *relname, char *usename, AclMode mode) } if (!heap_attisnull(tuple, Anum_pg_class_relacl)) { - tmp = (Acl *) heap_getattr(tuple, - Anum_pg_class_relacl, - RelationGetDescr(relation), - (bool *) NULL); - acl = makeacl(ACL_NUM(tmp)); - memmove((char *) acl, (char *) tmp, ACL_SIZE(tmp)); + /* get a detoasted copy of the ACL */ + acl = DatumGetAclPCopy(heap_getattr(tuple, + Anum_pg_class_relacl, + RelationGetDescr(relation), + (bool *) NULL)); } else { @@ -410,13 +423,10 @@ pg_aclcheck(char *relname, char *usename, AclMode mode) * if the acl is null, by default the owner can do whatever he * wants to with it */ - int4 ownerId; + AclId ownerId; - ownerId = (int4) heap_getattr(tuple, - Anum_pg_class_relowner, - RelationGetDescr(relation), - (bool *) NULL); - acl = aclownerdefault(relname, (AclId) ownerId); + ownerId = ((Form_pg_class) GETSTRUCT(tuple))->relowner; + acl = aclownerdefault(relname, ownerId); } heap_close(relation, RowExclusiveLock); #else @@ -427,12 +437,11 @@ pg_aclcheck(char *relname, char *usename, AclMode mode) if (HeapTupleIsValid(tuple) && !heap_attisnull(tuple, Anum_pg_class_relacl)) { - tmp = (Acl *) heap_getattr(tuple, - Anum_pg_class_relacl, - RelationGetDescr(relation), - (bool *) NULL); - acl = makeacl(ACL_NUM(tmp)); - memmove((char *) acl, (char *) tmp, ACL_SIZE(tmp)); + /* get a detoasted copy of the ACL */ + acl = DatumGetAclPCopy(heap_getattr(tuple, + Anum_pg_class_relacl, + RelationGetDescr(relation), + (bool *) NULL)); } heap_close(relation, RowExclusiveLock); #endif diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c index 4cbaba9b12f8531bcc702927da56bd5dc3be90cc..c4f1228dbcf05d1a6c55c188c6c99fba0c5c470f 100644 --- a/src/backend/utils/adt/acl.c +++ b/src/backend/utils/adt/acl.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.47 2000/06/14 18:17:42 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.48 2000/07/31 22:39:09 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -26,8 +26,8 @@ #include "utils/syscache.h" static char *getid(char *s, char *n); -static int32 aclitemeq(AclItem *a1, AclItem *a2); -static int32 aclitemgt(AclItem *a1, AclItem *a2); +static bool aclitemeq(AclItem *a1, AclItem *a2); +static bool aclitemgt(AclItem *a1, AclItem *a2); static char *aclparse(char *s, AclItem *aip, unsigned *modechg); #define ACL_IDTYPE_GID_KEYWORD "group" @@ -229,18 +229,14 @@ makeacl(int n) * RETURNS: * the new AclItem */ -AclItem * -aclitemin(char *s) +Datum +aclitemin(PG_FUNCTION_ARGS) { - unsigned modechg; + char *s = PG_GETARG_CSTRING(0); AclItem *aip; - - if (!s) - elog(ERROR, "aclitemin: null string"); + unsigned modechg; aip = (AclItem *) palloc(sizeof(AclItem)); - if (!aip) - elog(ERROR, "aclitemin: palloc failed"); s = aclparse(s, aip, &modechg); if (modechg != ACL_MODECHG_EQL) elog(ERROR, "aclitemin: cannot accept anything but = ACLs"); @@ -248,7 +244,7 @@ aclitemin(char *s) ++s; if (*s) elog(ERROR, "aclitemin: extra garbage at end of specification"); - return aip; + PG_RETURN_ACLITEM_P(aip); } /* @@ -259,24 +255,17 @@ aclitemin(char *s) * RETURNS: * the new string */ -char * -aclitemout(AclItem *aip) +Datum +aclitemout(PG_FUNCTION_ARGS) { + AclItem *aip = PG_GETARG_ACLITEM_P(0); char *p; char *out; HeapTuple htup; unsigned i; - static AclItem default_aclitem = {ACL_ID_WORLD, - ACL_IDTYPE_WORLD, - ACL_WORLD_DEFAULT}; char *tmpname; - if (!aip) - aip = &default_aclitem; - p = out = palloc(strlen("group =arwR ") + 1 + NAMEDATALEN); - if (!out) - elog(ERROR, "aclitemout: palloc failed"); *p = '\0'; switch (aip->ai_idtype) @@ -319,36 +308,28 @@ aclitemout(AclItem *aip) *p++ = ACL_MODE_STR[i]; *p = '\0'; - return out; + PG_RETURN_CSTRING(out); } /* * aclitemeq * aclitemgt * AclItem equality and greater-than comparison routines. - * Two AclItems are equal iff they are both NULL or they have the + * Two AclItems are equal iff they have the * same identifier (and identifier type). * * RETURNS: * a boolean value indicating = or > */ -static int32 +static bool aclitemeq(AclItem *a1, AclItem *a2) { - if (!a1 && !a2) - return 1; - if (!a1 || !a2) - return 0; return a1->ai_idtype == a2->ai_idtype && a1->ai_id == a2->ai_id; } -static int32 +static bool aclitemgt(AclItem *a1, AclItem *a2) { - if (a1 && !a2) - return 1; - if (!a1 || !a2) - return 0; return ((a1->ai_idtype > a2->ai_idtype) || (a1->ai_idtype == a2->ai_idtype && a1->ai_id > a2->ai_id)); } @@ -384,25 +365,28 @@ acldefault(char *relname) return acl; } +/* + * Add or replace an item in an ACL array. + * + * NB: caller is responsible for having detoasted the input ACL, if needed. + */ Acl * aclinsert3(Acl *old_acl, AclItem *mod_aip, unsigned modechg) { Acl *new_acl; AclItem *old_aip, *new_aip; - unsigned src, + int src, dst, num; + /* These checks for null input are probably dead code, but... */ if (!old_acl || ACL_NUM(old_acl) < 1) - { - new_acl = makeacl(0); - return new_acl; - } + old_acl = makeacl(0); if (!mod_aip) { new_acl = makeacl(ACL_NUM(old_acl)); - memmove((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl)); + memcpy((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl)); return new_acl; } @@ -422,7 +406,7 @@ aclinsert3(Acl *old_acl, AclItem *mod_aip, unsigned modechg) { /* modify in-place */ new_acl = makeacl(ACL_NUM(old_acl)); - memmove((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl)); + memcpy((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl)); new_aip = ACL_DAT(new_acl); src = dst; } @@ -470,60 +454,58 @@ aclinsert3(Acl *old_acl, AclItem *mod_aip, unsigned modechg) /* * if the newly added entry has no permissions, delete it from the * list. For example, this helps in removing entries for users who no - * longer exists... + * longer exist... */ - for (dst = 1; dst < num; dst++) + if (new_aip[dst].ai_mode == 0) { - if (new_aip[dst].ai_mode == 0) - { - int i; + int i; - for (i = dst + 1; i < num; i++) - { - new_aip[i - 1].ai_id = new_aip[i].ai_id; - new_aip[i - 1].ai_idtype = new_aip[i].ai_idtype; - new_aip[i - 1].ai_mode = new_aip[i].ai_mode; - } - ARR_DIMS(new_acl)[0] = num - 1; - /* Adjust also the array size because it is used for memmove */ - ARR_SIZE(new_acl) -= sizeof(AclItem); - break; + for (i = dst + 1; i < num; i++) + { + new_aip[i - 1].ai_id = new_aip[i].ai_id; + new_aip[i - 1].ai_idtype = new_aip[i].ai_idtype; + new_aip[i - 1].ai_mode = new_aip[i].ai_mode; } + ARR_DIMS(new_acl)[0] = num - 1; + /* Adjust also the array size because it is used for memmove */ + ARR_SIZE(new_acl) -= sizeof(AclItem); } return new_acl; } /* - * aclinsert - * + * aclinsert (exported function) */ -Acl * -aclinsert(Acl *old_acl, AclItem *mod_aip) +Datum +aclinsert(PG_FUNCTION_ARGS) { - return aclinsert3(old_acl, mod_aip, ACL_MODECHG_EQL); + Acl *old_acl = PG_GETARG_ACL_P(0); + AclItem *mod_aip = PG_GETARG_ACLITEM_P(1); + + PG_RETURN_ACL_P(aclinsert3(old_acl, mod_aip, ACL_MODECHG_EQL)); } -Acl * -aclremove(Acl *old_acl, AclItem *mod_aip) +Datum +aclremove(PG_FUNCTION_ARGS) { + Acl *old_acl = PG_GETARG_ACL_P(0); + AclItem *mod_aip = PG_GETARG_ACLITEM_P(1); Acl *new_acl; AclItem *old_aip, *new_aip; - unsigned dst, + int dst, old_num, new_num; + /* These checks for null input should be dead code, but... */ if (!old_acl || ACL_NUM(old_acl) < 1) - { - new_acl = makeacl(0); - return new_acl; - } + old_acl = makeacl(0); if (!mod_aip) { new_acl = makeacl(ACL_NUM(old_acl)); - memmove((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl)); - return new_acl; + memcpy((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl)); + PG_RETURN_ACL_P(new_acl); } old_num = ACL_NUM(old_acl); @@ -534,12 +516,12 @@ aclremove(Acl *old_acl, AclItem *mod_aip) if (dst >= old_num) { /* not found or empty */ new_acl = makeacl(ACL_NUM(old_acl)); - memmove((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl)); + memcpy((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl)); } else { new_num = old_num - 1; - new_acl = makeacl(ACL_NUM(old_acl) - 1); + new_acl = makeacl(new_num); new_aip = ACL_DAT(new_acl); if (dst == 0) { /* start */ @@ -561,23 +543,24 @@ aclremove(Acl *old_acl, AclItem *mod_aip) (new_num - dst) * sizeof(AclItem)); } } - return new_acl; + PG_RETURN_ACL_P(new_acl); } -int32 -aclcontains(Acl *acl, AclItem *aip) +Datum +aclcontains(PG_FUNCTION_ARGS) { - unsigned i, - num; + Acl *acl = PG_GETARG_ACL_P(0); + AclItem *aip = PG_GETARG_ACLITEM_P(1); AclItem *aidat; + int i, + num; - if (!acl || !aip || ((num = ACL_NUM(acl)) < 1)) - return 0; + num = ACL_NUM(acl); aidat = ACL_DAT(acl); for (i = 0; i < num; ++i) if (aclitemeq(aip, aidat + i)) - return 1; - return 0; + PG_RETURN_BOOL(true); + PG_RETURN_BOOL(false); } /* parser support routines */ @@ -638,7 +621,7 @@ aclmakepriv(char *old_privlist, char new_priv) * "G" - group * "U" - user * - * concatentates the two strings together with a space in between + * concatenates the two strings together with a space in between * * this routine is used in the parser * @@ -649,7 +632,7 @@ aclmakeuser(char *user_type, char *user) { char *user_list; - user_list = palloc(strlen(user) + 3); + user_list = palloc(strlen(user_type) + strlen(user) + 2); sprintf(user_list, "%s %s", user_type, user); return user_list; } diff --git a/src/include/catalog/pg_attribute.h b/src/include/catalog/pg_attribute.h index 925328e2bd9b564d11c626dd633759fd8d83597c..0ced47b064a6911cc59e5e840748efc7eb7ccf7c 100644 --- a/src/include/catalog/pg_attribute.h +++ b/src/include/catalog/pg_attribute.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_attribute.h,v 1.61 2000/07/03 23:10:05 wieck Exp $ + * $Id: pg_attribute.h,v 1.62 2000/07/31 22:39:06 tgl Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -124,15 +124,16 @@ CATALOG(pg_attribute) BOOTSTRAP char attstorage; - /* + /*---------- * attstorage tells for VARLENA attributes, what the heap access * methods can do to it if a given tuple doesn't fit into a page. - * Possible values are 'p': Value must be stored plain allways 'e': - * Value can be stored in "secondary" relation (if relation has - * rellongrelid attached) 'c': Value can be stored compressed inline - * 'x': Value can be stored compressed inline or in "secondary". - * - * Note: compressed storage + * Possible values are + * 'p': Value must be stored plain always + * 'e': Value can be stored in "secondary" relation (if relation + * has rellongrelid attached) + * 'm': Value can be stored compressed inline + * 'x': Value can be stored compressed inline or in "secondary" + *---------- */ bool attisset; @@ -439,7 +440,7 @@ DATA(insert OID = 0 ( 1249 tableoid 26 0 4 -7 0 -1 -1 t p f i f f)); { 1259, {"relhaspkey"}, 16, 0, 1, 18, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \ { 1259, {"relhasrules"}, 16, 0, 1, 19, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \ { 1259, {"relhassubclass"},16, 0, 1, 20, 0, -1, -1, '\001', 'p', '\0', 'c', '\0', '\0' }, \ -{ 1259, {"relacl"}, 1034, 0, -1, 21, 0, -1, -1, '\0', 'p', '\0', 'i', '\0', '\0' } +{ 1259, {"relacl"}, 1034, 0, -1, 21, 0, -1, -1, '\0', 'm', '\0', 'i', '\0', '\0' } DATA(insert OID = 0 ( 1259 relname 19 0 NAMEDATALEN 1 0 -1 -1 f p f i f f)); DATA(insert OID = 0 ( 1259 reltype 26 0 4 2 0 -1 -1 t p f i f f)); @@ -461,7 +462,7 @@ DATA(insert OID = 0 ( 1259 relrefs 21 0 2 17 0 -1 -1 t p f s f f)); DATA(insert OID = 0 ( 1259 relhaspkey 16 0 1 18 0 -1 -1 t p f c f f)); DATA(insert OID = 0 ( 1259 relhasrules 16 0 1 19 0 -1 -1 t p f c f f)); DATA(insert OID = 0 ( 1259 relhassubclass 16 0 1 20 0 -1 -1 t p f c f f)); -DATA(insert OID = 0 ( 1259 relacl 1034 0 -1 21 0 -1 -1 f p f i f f)); +DATA(insert OID = 0 ( 1259 relacl 1034 0 -1 21 0 -1 -1 f m f i f f)); DATA(insert OID = 0 ( 1259 ctid 27 0 6 -1 0 -1 -1 f p f i f f)); DATA(insert OID = 0 ( 1259 oid 26 0 4 -2 0 -1 -1 t p f i f f)); DATA(insert OID = 0 ( 1259 xmin 28 0 4 -3 0 -1 -1 t p f i f f)); diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 6b833400c08dd60b8416ce709409084c1d3eb422..7d06975b70286987360a81629a2dc058fc8689e0 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_proc.h,v 1.153 2000/07/30 22:14:01 tgl Exp $ + * $Id: pg_proc.h,v 1.154 2000/07/31 22:39:05 tgl Exp $ * * NOTES * The script catalog/genbki.sh reads this file and generates .bki @@ -1256,16 +1256,16 @@ DATA(insert OID = 1029 ( nullvalue PGUID 12 f t t f 1 f 16 "0" 100 0 0 100 DESCR("(internal)"); DATA(insert OID = 1030 ( nonnullvalue PGUID 12 f t t f 1 f 16 "0" 100 0 0 100 nonnullvalue - )); DESCR("(internal)"); -DATA(insert OID = 1031 ( aclitemin PGUID 11 f t f t 1 f 1033 "0" 100 0 0 100 aclitemin - )); +DATA(insert OID = 1031 ( aclitemin PGUID 12 f t f t 1 f 1033 "0" 100 0 0 100 aclitemin - )); DESCR("(internal)"); -DATA(insert OID = 1032 ( aclitemout PGUID 11 f t f t 1 f 23 "0" 100 0 0 100 aclitemout - )); +DATA(insert OID = 1032 ( aclitemout PGUID 12 f t f t 1 f 23 "1033" 100 0 0 100 aclitemout - )); DESCR("(internal)"); -DATA(insert OID = 1035 ( aclinsert PGUID 11 f t f t 2 f 1034 "1034 1033" 100 0 0 100 aclinsert - )); -DESCR("addition"); -DATA(insert OID = 1036 ( aclremove PGUID 11 f t f t 2 f 1034 "1034 1033" 100 0 0 100 aclremove - )); -DESCR("subtract"); -DATA(insert OID = 1037 ( aclcontains PGUID 11 f t f t 2 f 16 "1034 1033" 100 0 0 100 aclcontains - )); -DESCR("matches regex., case-sensitive"); +DATA(insert OID = 1035 ( aclinsert PGUID 12 f t f t 2 f 1034 "1034 1033" 100 0 0 100 aclinsert - )); +DESCR("add/update ACL item"); +DATA(insert OID = 1036 ( aclremove PGUID 12 f t f t 2 f 1034 "1034 1033" 100 0 0 100 aclremove - )); +DESCR("remove ACL item"); +DATA(insert OID = 1037 ( aclcontains PGUID 12 f t f t 2 f 16 "1034 1033" 100 0 0 100 aclcontains - )); +DESCR("does ACL contain item?"); DATA(insert OID = 1038 ( seteval PGUID 12 f t f t 1 f 23 "26" 100 0 0 100 seteval - )); DESCR(""); DATA(insert OID = 1044 ( bpcharin PGUID 12 f t t t 3 f 1042 "0 26 23" 100 0 0 100 bpcharin - )); diff --git a/src/include/postgres.h b/src/include/postgres.h index f11e28ed9f927f1a5a46d6541ad5a7ab19bb5027..1011d04cbbdd37d3406398276a922426e96cba37 100644 --- a/src/include/postgres.h +++ b/src/include/postgres.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1995, Regents of the University of California * - * $Id: postgres.h,v 1.43 2000/07/03 23:09:56 wieck Exp $ + * $Id: postgres.h,v 1.44 2000/07/31 22:39:03 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -46,8 +46,6 @@ * ---------------------------------------------------------------- */ -typedef int4 aclitem; - #define InvalidOid ((Oid) 0) #define OidIsValid(objectId) ((bool) ((objectId) != InvalidOid)) @@ -57,6 +55,8 @@ typedef Oid RegProcedure; #define RegProcedureIsValid(p) OidIsValid(p) +typedef int4 aclitem; /* PHONY definition for catalog use only */ + /* ---------------------------------------------------------------- * Section 2: variable length and array types * ---------------------------------------------------------------- diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h index f1f60fca4cd154add5e6f899a0a4e5206e9a5a5d..e8a8f3a111b4549b7d1037c1ea09490351371516 100644 --- a/src/include/utils/acl.h +++ b/src/include/utils/acl.h @@ -7,17 +7,16 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: acl.h,v 1.25 2000/04/12 17:16:54 momjian Exp $ + * $Id: acl.h,v 1.26 2000/07/31 22:39:02 tgl Exp $ * * NOTES - * For backward-compatability purposes we have to allow there + * For backward-compatibility purposes we have to allow there * to be a null ACL in a pg_class tuple. This will be defined as * meaning "no protection" (i.e., old catalogs get old semantics). * * The AclItems in an ACL array are currently kept in sorted order. * Things will break hard if you change that without changing the * code wherever this is included. - * *------------------------------------------------------------------------- */ #ifndef ACL_H @@ -78,7 +77,7 @@ typedef struct AclItem AclMode ai_mode; /* - * This is actually type 'aclitem', and we want a fixed size for for + * This is actually type 'aclitem', and we want a fixed size for * all platforms, so we pad this with dummies. */ char dummy1, @@ -88,22 +87,30 @@ typedef struct AclItem /* Note: if the size of AclItem changes, change the aclitem typlen in pg_type.h */ + /* - * The value of the first dimension-array element. Since these arrays - * always have a lower-bound of 0, this is the same as the number of - * elements in the array. + * Definitions for convenient access to Acl (array of AclItem) and IdList + * (array of AclId). These are standard Postgres arrays, but are restricted + * to have one dimension. We also ignore the lower bound when reading, + * and set it to zero when writing. + * + * CAUTION: as of Postgres 7.1, these arrays are toastable (just like all + * other array types). Therefore, be careful to detoast them with the + * macros provided, unless you know for certain that a particular array + * can't have been toasted. Presently, we do not provide toast tables for + * pg_class or pg_group, so the entries in those tables won't have been + * stored externally --- but they could have been compressed! */ -#define ARR_DIM0(a) (((unsigned *) (((char *) a) + sizeof(ArrayType)))[0]) + /* * Acl a one-dimensional POSTGRES array of AclItem */ typedef ArrayType Acl; -#define ACL_NUM(ACL) ARR_DIM0(ACL) +#define ACL_NUM(ACL) (ARR_DIMS(ACL)[0]) #define ACL_DAT(ACL) ((AclItem *) ARR_DATA_PTR(ACL)) -#define ACL_N_SIZE(N) \ - ((unsigned) (ARR_OVERHEAD(1) + ((N) * sizeof(AclItem)))) +#define ACL_N_SIZE(N) (ARR_OVERHEAD(1) + ((N) * sizeof(AclItem))) #define ACL_SIZE(ACL) ARR_SIZE(ACL) /* @@ -111,12 +118,32 @@ typedef ArrayType Acl; */ typedef ArrayType IdList; -#define IDLIST_NUM(IDL) ARR_DIM0(IDL) +#define IDLIST_NUM(IDL) (ARR_DIMS(IDL)[0]) #define IDLIST_DAT(IDL) ((AclId *) ARR_DATA_PTR(IDL)) -#define IDLIST_N_SIZE(N) \ - ((unsigned) (ARR_OVERHEAD(1) + ((N) * sizeof(AclId)))) +#define IDLIST_N_SIZE(N) (ARR_OVERHEAD(1) + ((N) * sizeof(AclId))) #define IDLIST_SIZE(IDL) ARR_SIZE(IDL) +/* + * fmgr macros for these types + */ +#define DatumGetAclItemP(X) ((AclItem *) DatumGetPointer(X)) +#define PG_GETARG_ACLITEM_P(n) DatumGetAclItemP(PG_GETARG_DATUM(n)) +#define PG_RETURN_ACLITEM_P(x) PG_RETURN_POINTER(x) + +#define DatumGetAclP(X) ((Acl *) PG_DETOAST_DATUM(X)) +#define DatumGetAclPCopy(X) ((Acl *) PG_DETOAST_DATUM_COPY(X)) +#define PG_GETARG_ACL_P(n) DatumGetAclP(PG_GETARG_DATUM(n)) +#define PG_GETARG_ACL_P_COPY(n) DatumGetAclPCopy(PG_GETARG_DATUM(n)) +#define PG_RETURN_ACL_P(x) PG_RETURN_POINTER(x) + +#define DatumGetIdListP(X) ((IdList *) PG_DETOAST_DATUM(X)) +#define DatumGetIdListPCopy(X) ((IdList *) PG_DETOAST_DATUM_COPY(X)) +#define PG_GETARG_IDLIST_P(n) DatumGetIdListP(PG_GETARG_DATUM(n)) +#define PG_GETARG_IDLIST_P_COPY(n) DatumGetIdListPCopy(PG_GETARG_DATUM(n)) +#define PG_RETURN_IDLIST_P(x) PG_RETURN_POINTER(x) + + +/* mode indicators for I/O */ #define ACL_MODECHG_STR "+-=" /* list of valid characters */ #define ACL_MODECHG_ADD_CHR '+' #define ACL_MODECHG_DEL_CHR '-' @@ -157,11 +184,11 @@ extern ChangeACLStmt *makeAclStmt(char *privs, List *rel_list, char *grantee, * exported routines (from acl.c) */ extern Acl *makeacl(int n); -extern AclItem *aclitemin(char *s); -extern char *aclitemout(AclItem *aip); -extern Acl *aclinsert(Acl *old_acl, AclItem *mod_aip); -extern Acl *aclremove(Acl *old_acl, AclItem *mod_aip); -extern int32 aclcontains(Acl *acl, AclItem *aip); +extern Datum aclitemin(PG_FUNCTION_ARGS); +extern Datum aclitemout(PG_FUNCTION_ARGS); +extern Datum aclinsert(PG_FUNCTION_ARGS); +extern Datum aclremove(PG_FUNCTION_ARGS); +extern Datum aclcontains(PG_FUNCTION_ARGS); /* * prototypes for functions in aclchk.c