]> granicus.if.org Git - postgresql/commitdiff
Make acl-related functions safe for TOAST. Mark pg_class.relacl as
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 31 Jul 2000 22:39:17 +0000 (22:39 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 31 Jul 2000 22:39:17 +0000 (22:39 +0000)
compressible but not externally storable (since we're not sure about
whether creating a toast relation for pg_class would work).

src/backend/access/heap/tuptoaster.c
src/backend/catalog/aclchk.c
src/backend/utils/adt/acl.c
src/include/catalog/pg_attribute.h
src/include/catalog/pg_proc.h
src/include/postgres.h
src/include/utils/acl.h

index 482bb924dcb4320e06c66002cf7087f1e3da876d..bab118573037a667be0b1c751f78727b7752b95b 100644 (file)
@@ -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';
index c342b067ff4078b610db7eae0eb8197d6d8894b7..6be489a0c74eb7a5650f15f988aa33c22c56a0eb 100644 (file)
@@ -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
index 4cbaba9b12f8531bcc702927da56bd5dc3be90cc..c4f1228dbcf05d1a6c55c188c6c99fba0c5c470f 100644 (file)
@@ -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;
 }
index 925328e2bd9b564d11c626dd633759fd8d83597c..0ced47b064a6911cc59e5e840748efc7eb7ccf7c 100644 (file)
@@ -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));
index 6b833400c08dd60b8416ce709409084c1d3eb422..7d06975b70286987360a81629a2dc058fc8689e0 100644 (file)
@@ -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 - ));
index f11e28ed9f927f1a5a46d6541ad5a7ab19bb5027..1011d04cbbdd37d3406398276a922426e96cba37 100644 (file)
@@ -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
  * ----------------------------------------------------------------
index f1f60fca4cd154add5e6f899a0a4e5206e9a5a5d..e8a8f3a111b4549b7d1037c1ea09490351371516 100644 (file)
@@ -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