Make acl-related functions safe for TOAST. Mark pg_class.relacl as
authorTom Lane
Mon, 31 Jul 2000 22:39:17 +0000 (22:39 +0000)
committerTom Lane
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