]> granicus.if.org Git - postgresql/commitdiff
Support toasting of shared system relations, and provide toast tables for
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 27 Apr 2002 21:24:34 +0000 (21:24 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 27 Apr 2002 21:24:34 +0000 (21:24 +0000)
pg_database, pg_shadow, pg_group, all of which now have potentially-long
fields.  Along the way, get rid of SharedSystemRelationNames list: shared
rels are now identified in their include/pg_catalog/*.h files by a
BKI_SHARED_RELATION macro, while indexes and toast rels inherit sharedness
automatically from their parent table.  Fix some bugs with failure to detoast
pg_group.grolist during ALTER GROUP.

27 files changed:
src/backend/bootstrap/bootparse.y
src/backend/bootstrap/bootscanner.l
src/backend/bootstrap/bootstrap.c
src/backend/catalog/README
src/backend/catalog/catalog.c
src/backend/catalog/genbki.sh
src/backend/catalog/heap.c
src/backend/catalog/index.c
src/backend/commands/cluster.c
src/backend/commands/dbcommands.c
src/backend/commands/tablecmds.c
src/backend/commands/user.c
src/backend/executor/execMain.c
src/backend/utils/cache/relcache.c
src/backend/utils/init/globals.c
src/backend/utils/init/miscinit.c
src/backend/utils/init/postinit.c
src/bin/initdb/initdb.sh
src/include/bootstrap/bootstrap.h
src/include/catalog/catalog.h
src/include/catalog/catname.h
src/include/catalog/catversion.h
src/include/catalog/heap.h
src/include/catalog/pg_database.h
src/include/catalog/pg_group.h
src/include/catalog/pg_shadow.h
src/include/postgres.h

index e98eae3a423fffeeb28d539ec2e378f05a862d09..e6250d0c501ba808cf64cdb04b6b059530d5de81 100644 (file)
@@ -1,15 +1,15 @@
 %{
 /*-------------------------------------------------------------------------
  *
- * backendparse.y
- *       yacc parser grammer for the "backend" initialization program.
+ * bootparse.y
+ *       yacc parser grammar for the "backend" initialization program.
  *
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/bootstrap/bootparse.y,v 1.45 2002/04/17 20:57:56 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/bootstrap/bootparse.y,v 1.46 2002/04/27 21:24:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -88,8 +88,9 @@ int num_columns_read = 0;
 
 %type <list>  boot_index_params
 %type <ielem> boot_index_param
-%type <ival> boot_const boot_ident
-%type <ival> optbootstrap optwithoutoids boot_tuple boot_tuplelist
+%type <ival>  boot_const boot_ident
+%type <ival>  optbootstrap optsharedrelation optwithoutoids
+%type <ival>  boot_tuple boot_tuplelist
 %type <oidval> optoideq
 
 %token <ival> CONST ID
@@ -97,7 +98,7 @@ int num_columns_read = 0;
 %token STRING XDEFINE
 %token XDECLARE INDEX ON USING XBUILD INDICES UNIQUE
 %token COMMA EQUALS LPAREN RPAREN
-%token OBJ_ID XBOOTSTRAP XWITHOUT_OIDS NULLVAL
+%token OBJ_ID XBOOTSTRAP XSHARED_RELATION XWITHOUT_OIDS NULLVAL
 %start TopLevel
 
 %nonassoc low
@@ -150,16 +151,14 @@ Boot_CloseStmt:
                ;
 
 Boot_CreateStmt:
-                 XCREATE optbootstrap optwithoutoids boot_ident LPAREN
+                 XCREATE optbootstrap optsharedrelation optwithoutoids boot_ident LPAREN
                                {
                                        do_start();
                                        numattr = 0;
-                                       if ($2)
-                                               elog(DEBUG3, "creating bootstrap relation %s...",
-                                                        LexIDStr($4));
-                                       else
-                                               elog(DEBUG3, "creating relation %s...",
-                                                        LexIDStr($4));
+                                       elog(DEBUG3, "creating%s%s relation %s...",
+                                                $2 ? " bootstrap" : "",
+                                                $3 ? " shared" : "",
+                                                LexIDStr($5));
                                }
                  boot_typelist
                                {
@@ -171,21 +170,22 @@ Boot_CreateStmt:
 
                                        if ($2)
                                        {
-                                               extern Relation reldesc;
                                                TupleDesc tupdesc;
 
-                                               if (reldesc)
+                                               if (boot_reldesc)
                                                {
                                                        elog(DEBUG3, "create bootstrap: warning, open relation exists, closing first");
                                                        closerel(NULL);
                                                }
 
                                                tupdesc = CreateTupleDesc(numattr, attrtypes);
-                                               reldesc = heap_create(LexIDStr($4),
-                                                                                         PG_CATALOG_NAMESPACE,
-                                                                                         tupdesc,
-                                                                                         true, true);
-                                               reldesc->rd_rel->relhasoids = ! ($3);
+                                               boot_reldesc = heap_create(LexIDStr($5),
+                                                                                                  PG_CATALOG_NAMESPACE,
+                                                                                                  tupdesc,
+                                                                                                  $3,
+                                                                                                  true,
+                                                                                                  true);
+                                               boot_reldesc->rd_rel->relhasoids = ! ($4);
                                                elog(DEBUG3, "bootstrap relation created");
                                        }
                                        else
@@ -194,11 +194,12 @@ Boot_CreateStmt:
                                                TupleDesc tupdesc;
 
                                                tupdesc = CreateTupleDesc(numattr,attrtypes);
-                                               id = heap_create_with_catalog(LexIDStr($4),
+                                               id = heap_create_with_catalog(LexIDStr($5),
                                                                                                          PG_CATALOG_NAMESPACE,
                                                                                                          tupdesc,
                                                                                                          RELKIND_RELATION,
-                                                                                                         ! ($3),
+                                                                                                         $3,
+                                                                                                         ! ($4),
                                                                                                          true);
                                                elog(DEBUG3, "relation created with oid %u", id);
                                        }
@@ -221,7 +222,7 @@ Boot_InsertStmt:
                                        if (num_columns_read != numattr)
                                                elog(ERROR, "incorrect number of columns in row (expected %d, got %d)",
                                                         numattr, num_columns_read);
-                                       if (reldesc == (Relation)NULL)
+                                       if (boot_reldesc == (Relation) NULL)
                                        {
                                                elog(ERROR, "relation not open");
                                                err_out();
@@ -283,6 +284,11 @@ optbootstrap:
                |                               { $$ = 0; }
                ;
 
+optsharedrelation:
+                       XSHARED_RELATION        { $$ = 1; }
+               |                                               { $$ = 0; }
+               ;
+
 optwithoutoids:
                        XWITHOUT_OIDS   { $$ = 1; }
                |                                       { $$ = 0; }
index 47f0c8c1313631909dbbbde5194cbbcef6bdaf99..b471dcc66e9f836c55ab96aaaf7abf3c9f008d02 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/bootstrap/bootscanner.l,v 1.21 2001/08/10 18:57:33 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/bootstrap/bootscanner.l,v 1.22 2002/04/27 21:24:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -71,6 +71,8 @@ create                        { return(XCREATE); }
 
 OID                            { return(OBJ_ID); }
 bootstrap              { return(XBOOTSTRAP); }
+"shared_relation"      { return(XSHARED_RELATION); }
+"without_oids" { return(XWITHOUT_OIDS); }
 _null_                 { return(NULLVAL); }
 
 insert                 { return(INSERT_TUPLE); }
@@ -94,7 +96,6 @@ insert                        { return(INSERT_TUPLE); }
 "index"                        { return(INDEX); }
 "on"                   { return(ON); }
 "using"                        { return(USING); }
-"without_oids" { return(XWITHOUT_OIDS); }
 
 {arrayid}              {
                                        yylval.ival = EnterString(MapArrayTypeName((char*)yytext));
index 07d013232c70bf5072586f622b590ddb0c5b7dd9..6028b2db484975afaf42904826801e1b60cc4639 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.126 2002/04/25 02:56:55 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.127 2002/04/27 21:24:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -59,6 +59,9 @@ static void cleanup(void);
  *             global variables
  * ----------------
  */
+
+Relation       boot_reldesc;           /* current relation descriptor */
+
 /*
  * In the lexical analyzer, we need to get the reference number quickly from
  * the string, and the string from the reference number.  Thus we have
@@ -500,20 +503,20 @@ boot_openrel(char *relname)
                heap_close(rel, NoLock);
        }
 
-       if (reldesc != NULL)
+       if (boot_reldesc != NULL)
                closerel(NULL);
 
        elog(DEBUG3, "open relation %s, attrsize %d", relname ? relname : "(null)",
                 (int) ATTRIBUTE_TUPLE_SIZE);
 
-       reldesc = heap_openr(relname, NoLock);
-       numattr = reldesc->rd_rel->relnatts;
+       boot_reldesc = heap_openr(relname, NoLock);
+       numattr = boot_reldesc->rd_rel->relnatts;
        for (i = 0; i < numattr; i++)
        {
                if (attrtypes[i] == NULL)
                        attrtypes[i] = AllocateAttribute();
                memmove((char *) attrtypes[i],
-                               (char *) reldesc->rd_att->attrs[i],
+                               (char *) boot_reldesc->rd_att->attrs[i],
                                ATTRIBUTE_TUPLE_SIZE);
 
                /* Some old pg_attribute tuples might not have attisset. */
@@ -523,8 +526,9 @@ boot_openrel(char *relname)
                 * defined yet.
                 */
                if (namestrcmp(&attrtypes[i]->attname, "attisset") == 0)
-                       attrtypes[i]->attisset = get_attisset(RelationGetRelid(reldesc),
-                                                                                NameStr(attrtypes[i]->attname));
+                       attrtypes[i]->attisset =
+                               get_attisset(RelationGetRelid(boot_reldesc),
+                                                        NameStr(attrtypes[i]->attname));
                else
                        attrtypes[i]->attisset = false;
 
@@ -547,9 +551,9 @@ closerel(char *name)
 {
        if (name)
        {
-               if (reldesc)
+               if (boot_reldesc)
                {
-                       if (strcmp(RelationGetRelationName(reldesc), name) != 0)
+                       if (strcmp(RelationGetRelationName(boot_reldesc), name) != 0)
                                elog(ERROR, "closerel: close of '%s' when '%s' was expected",
                                         name, relname ? relname : "(null)");
                }
@@ -559,13 +563,13 @@ closerel(char *name)
 
        }
 
-       if (reldesc == NULL)
+       if (boot_reldesc == NULL)
                elog(ERROR, "no open relation to close");
        else
        {
                elog(DEBUG3, "close relation %s", relname ? relname : "(null)");
-               heap_close(reldesc, NoLock);
-               reldesc = (Relation) NULL;
+               heap_close(boot_reldesc, NoLock);
+               boot_reldesc = (Relation) NULL;
        }
 }
 
@@ -585,7 +589,7 @@ DefineAttr(char *name, char *type, int attnum)
        int                     attlen;
        Oid                     typeoid;
 
-       if (reldesc != NULL)
+       if (boot_reldesc != NULL)
        {
                elog(LOG, "warning: no open relations allowed with 'create' command");
                closerel(relname);
@@ -674,7 +678,7 @@ InsertOneTuple(Oid objectid)
 
        if (objectid != (Oid) 0)
                tuple->t_data->t_oid = objectid;
-       heap_insert(reldesc, tuple);
+       heap_insert(boot_reldesc, tuple);
        heap_freetuple(tuple);
        elog(DEBUG3, "row inserted");
 
@@ -706,13 +710,13 @@ InsertOneValue(char *value, int i)
 
                elog(DEBUG3, "Typ != NULL");
                app = Typ;
-               while (*app && (*app)->am_oid != reldesc->rd_att->attrs[i]->atttypid)
+               while (*app && (*app)->am_oid != boot_reldesc->rd_att->attrs[i]->atttypid)
                        ++app;
                ap = *app;
                if (ap == NULL)
                {
                        elog(FATAL, "unable to find atttypid %u in Typ list",
-                                reldesc->rd_att->attrs[i]->atttypid);
+                                boot_reldesc->rd_att->attrs[i]->atttypid);
                }
                values[i] = OidFunctionCall3(ap->am_typ.typinput,
                                                                         CStringGetDatum(value),
@@ -806,8 +810,8 @@ cleanup()
                elog(FATAL, "Memory manager fault: cleanup called twice.\n");
                proc_exit(1);
        }
-       if (reldesc != (Relation) NULL)
-               heap_close(reldesc, NoLock);
+       if (boot_reldesc != (Relation) NULL)
+               heap_close(boot_reldesc, NoLock);
        CommitTransactionCommand();
        proc_exit(Warnings);
 }
index 26dac4892af7bba74f700e8c0e827f935c27774d..2a688eda1ba7611144517b99f4efb06766904290 100644 (file)
@@ -1,4 +1,4 @@
-$Header: /cvsroot/pgsql/src/backend/catalog/README,v 1.6 2002/04/15 23:46:13 momjian Exp $
+$Header: /cvsroot/pgsql/src/backend/catalog/README,v 1.7 2002/04/27 21:24:33 tgl Exp $
 
 This directory contains .c files that manipulate the system catalogs;
 src/include/catalog contains the .h files that define the structure
@@ -69,15 +69,14 @@ manually create appropriate entries for them in the pre-loaded contents of
 pg_class, pg_attribute, and pg_type.  You'll also need to add code to function
 heap_create() in heap.c to force the correct OID to be assigned when the table
 is first referenced.  (It's near the top of the function with the comment
-beginning in 'Real ugly stuff'.)  Avoid making new catalogs be bootstrap
+beginning in "Real ugly stuff".)  Avoid making new catalogs be bootstrap
 catalogs if at all possible; generally, only tables that must be written to
 in order to create a table should be bootstrapped.
 
 - Certain BOOTSTRAP tables must be at the start of the Makefile
-POSTGRES_BKI_SRCS variable, as these will not be created through standard
-function means, but will be written directly to disk.  That's how pg_class is
-created without depending on functions which depend on the existence of
-pg_class.  The list of files this currently includes is:
+POSTGRES_BKI_SRCS variable, as these will not be created through the standard
+heap_create_with_catalog process, because it needs these tables to exist
+already.  The list of files this currently includes is:
        pg_proc.h pg_type.h pg_attribute.h pg_class.h
 Also, indexing.h must be last, since the indexes can't be created until all
 the tables are in place.  There are reputedly some other order dependencies
index 6e198772754b553d44adb0201030fb31233d040f..251ecacf2f0b524f1889b8d20f361e3cbac9d952 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/catalog.c,v 1.45 2002/04/12 20:38:18 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/catalog.c,v 1.46 2002/04/27 21:24:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -177,29 +177,6 @@ IsReservedName(const char *name)
                        name[2] == '_');
 }
 
-/*
- * IsSharedSystemRelationName
- *             True iff name is the name of a shared system catalog relation.
- *
- *             Note: This function assumes that this is a system relation
- *             in the first place.  If that is not known, check the namespace
- *             (with IsSystemNamespace) before calling this function.
- */
-bool
-IsSharedSystemRelationName(const char *relname)
-{
-       int                     i;
-
-       i = 0;
-       while (SharedSystemRelationNames[i] != NULL)
-       {
-               if (strcmp(SharedSystemRelationNames[i], relname) == 0)
-                       return TRUE;
-               i++;
-       }
-       return FALSE;
-}
-
 
 /*
  *             newoid                  - returns a unique identifier across all catalogs.
index 4edb86cdba96f9fd7bf10b9fa7adec0fb5c644a5..94db1c65189ec6bac0068ee6fc34d8979037c7ed 100644 (file)
@@ -10,7 +10,7 @@
 #
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/backend/catalog/Attic/genbki.sh,v 1.26 2002/03/26 19:15:24 tgl Exp $
+#    $Header: /cvsroot/pgsql/src/backend/catalog/Attic/genbki.sh,v 1.27 2002/04/27 21:24:33 tgl Exp $
 #
 # NOTES
 #    non-essential whitespace is removed from the generated file.
@@ -217,6 +217,7 @@ BEGIN {
        inside = 0;
        raw = 0;
        bootstrap = "";
+       shared_relation = "";
        without_oids = "";
        nc = 0;
        reln_open = 0;
@@ -331,6 +332,9 @@ raw == 1    { print; next; }
        if ($0 ~ /BOOTSTRAP/) {
                bootstrap = "bootstrap ";
        }
+       if ($0 ~ /BKI_SHARED_RELATION/) {
+               shared_relation = "shared_relation ";
+       }
        if ($0 ~ /BKI_WITHOUT_OIDS/) {
                without_oids = "without_oids ";
        }
@@ -358,7 +362,7 @@ inside == 1 {
 #  if this is the last line, then output the bki catalog stuff.
 # ----
        if ($1 ~ /}/) {
-               print "create " bootstrap without_oids catalog;
+               print "create " bootstrap shared_relation without_oids catalog;
                print "\t(";
 
                for (j=1; j<i-1; j++) {
@@ -375,6 +379,7 @@ inside == 1 {
                reln_open = 1;
                inside = 0;
                bootstrap = "";
+               shared_relation = "";
                without_oids = "";
                next;
        }
index eb7487ae62d44923d34de4843fd0a4a83362d3b4..c6e097ede58164aef16d7f5f257579012ca52786 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.196 2002/04/12 20:38:18 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.197 2002/04/27 21:24:33 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -210,11 +210,12 @@ Relation
 heap_create(const char *relname,
                        Oid relnamespace,
                        TupleDesc tupDesc,
+                       bool shared_relation,
                        bool storage_create,
                        bool allow_system_table_mods)
 {
        Oid                     relid;
-       Oid                     dbid = MyDatabaseId;
+       Oid                     dbid = shared_relation ? InvalidOid : MyDatabaseId;
        bool            nailme = false;
        RelFileNode     rnode;
        Relation        rel;
@@ -225,16 +226,15 @@ heap_create(const char *relname,
        if (!allow_system_table_mods &&
                (IsSystemNamespace(relnamespace) || IsToastNamespace(relnamespace)) &&
                IsNormalProcessingMode())
-               elog(ERROR, "invalid relation \"%s\"; "
+               elog(ERROR, "cannot create %s.%s: "
                         "system catalog modifications are currently disallowed",
-                        relname);
+                        get_namespace_name(relnamespace), relname);
 
        /*
         * Real ugly stuff to assign the proper relid in the relation
         * descriptor follows.  Note that only "bootstrapped" relations whose
-        * OIDs are hard-coded in pg_class.h need be listed here.  We also
-        * have to take special care for those rels that should be nailed
-        * in cache and/or are shared across databases.
+        * OIDs are hard-coded in pg_class.h should be listed here.  We also
+        * have to recognize those rels that must be nailed in cache.
         */
        if (IsSystemNamespace(relnamespace))
        {
@@ -260,24 +260,19 @@ heap_create(const char *relname,
                }
                else if (strcmp(ShadowRelationName, relname) == 0)
                {
-                       dbid = InvalidOid;
                        relid = RelOid_pg_shadow;
                }
                else if (strcmp(GroupRelationName, relname) == 0)
                {
-                       dbid = InvalidOid;
                        relid = RelOid_pg_group;
                }
                else if (strcmp(DatabaseRelationName, relname) == 0)
                {
-                       dbid = InvalidOid;
                        relid = RelOid_pg_database;
                }
                else
                {
                        relid = newoid();
-                       if (IsSharedSystemRelationName(relname))
-                               dbid = InvalidOid;
                }
        }
        else
@@ -651,6 +646,7 @@ heap_create_with_catalog(const char *relname,
                                                 Oid relnamespace,
                                                 TupleDesc tupdesc,
                                                 char relkind,
+                                                bool shared_relation,
                                                 bool relhasoids,
                                                 bool allow_system_table_mods)
 {
@@ -678,8 +674,12 @@ heap_create_with_catalog(const char *relname,
         * necessary anymore, but we may as well avoid the cycles of creating
         * and deleting the file in case we fail.)
         */
-       new_rel_desc = heap_create(relname, relnamespace, tupdesc,
-                                                          false, allow_system_table_mods);
+       new_rel_desc = heap_create(relname,
+                                                          relnamespace,
+                                                          tupdesc,
+                                                          shared_relation,
+                                                          false,
+                                                          allow_system_table_mods);
 
        /* Fetch the relation OID assigned by heap_create */
        new_rel_oid = new_rel_desc->rd_att->attrs[0]->attrelid;
index d563d6541836a1e57505fb31d1b21814b7262172..cc17b7192374de66531ce95dfd0b492d8dac9864 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.176 2002/04/12 20:38:19 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.177 2002/04/27 21:24:34 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -67,7 +67,6 @@ static TupleDesc BuildFuncTupleDesc(Oid funcOid,
 static TupleDesc ConstructTupleDescriptor(Relation heapRelation,
                                                 int numatts, AttrNumber *attNums,
                                                 Oid *classObjectId);
-static void ConstructIndexReldesc(Relation indexRelation, Oid amoid);
 static void UpdateRelationRelation(Relation indexRelation);
 static void InitializeAttributeOids(Relation indexRelation,
                                                int numatts, Oid indexoid);
@@ -305,26 +304,6 @@ ConstructTupleDescriptor(Relation heapRelation,
        return indexTupDesc;
 }
 
-/* ----------------------------------------------------------------
- *             ConstructIndexReldesc
- * ----------------------------------------------------------------
- */
-static void
-ConstructIndexReldesc(Relation indexRelation, Oid amoid)
-{
-       /*
-        * Set up some additional fields of the index' pg_class entry. In
-        * particular, initialize knowledge of whether the index is shared.
-        */
-       indexRelation->rd_rel->relowner = GetUserId();
-       indexRelation->rd_rel->relam = amoid;
-       indexRelation->rd_rel->relisshared =
-               IsSystemNamespace(RelationGetNamespace(indexRelation)) &&
-               IsSharedSystemRelationName(RelationGetRelationName(indexRelation));
-       indexRelation->rd_rel->relkind = RELKIND_INDEX;
-       indexRelation->rd_rel->relhasoids = false;
-}
-
 /* ----------------------------------------------------------------
  *             UpdateRelationRelation
  * ----------------------------------------------------------------
@@ -561,6 +540,7 @@ index_create(Oid heapRelationId,
        Relation        heapRelation;
        Relation        indexRelation;
        TupleDesc       indexTupDesc;
+       bool            shared_relation;
        Oid                     namespaceId;
        Oid                     indexoid;
 
@@ -571,7 +551,12 @@ index_create(Oid heapRelationId,
         */
        heapRelation = heap_open(heapRelationId, ShareLock);
 
+       /*
+        * The index will be in the same namespace as its parent table,
+        * and is shared across databases if and only if the parent is.
+        */
        namespaceId = RelationGetNamespace(heapRelation);
+       shared_relation = heapRelation->rd_rel->relisshared;
 
        /*
         * check parameters
@@ -585,6 +570,16 @@ index_create(Oid heapRelationId,
                IsNormalProcessingMode())
                elog(ERROR, "User-defined indexes on system catalogs are not supported");
 
+       /*
+        * We cannot allow indexing a shared relation after initdb (because
+        * there's no way to make the entry in other databases' pg_class).
+        * Unfortunately we can't distinguish initdb from a manually started
+        * standalone backend.  However, we can at least prevent this mistake
+        * under normal multi-user operation.
+        */
+       if (shared_relation && IsUnderPostmaster)
+               elog(ERROR, "Shared indexes cannot be created after initdb");
+
        if (get_relname_relid(indexRelationName, namespaceId))
                elog(ERROR, "index named \"%s\" already exists",
                         indexRelationName);
@@ -607,6 +602,7 @@ index_create(Oid heapRelationId,
        indexRelation = heap_create(indexRelationName,
                                                                namespaceId,
                                                                indexTupDesc,
+                                                               shared_relation,
                                                                false,
                                                                allow_system_table_mods);
        indexoid = RelationGetRelid(indexRelation);
@@ -619,16 +615,18 @@ index_create(Oid heapRelationId,
        LockRelation(indexRelation, AccessExclusiveLock);
 
        /*
-        * construct the index relation descriptor
+        * Fill in fields of the index's pg_class entry that are not set
+        * correctly by heap_create.
         *
-        * XXX should have a proper way to create cataloged relations
+        * XXX should have a cleaner way to create cataloged indexes
         */
-       ConstructIndexReldesc(indexRelation, accessMethodObjectId);
+       indexRelation->rd_rel->relowner = GetUserId();
+       indexRelation->rd_rel->relam = accessMethodObjectId;
+       indexRelation->rd_rel->relkind = RELKIND_INDEX;
+       indexRelation->rd_rel->relhasoids = false;
 
-       /* ----------------
-        *        add index to catalogs
-        *        (append RELATION tuple)
-        * ----------------
+       /*
+        * store index's pg_class entry
         */
        UpdateRelationRelation(indexRelation);
 
index 8883eddc49f7d0c9342507e2d063f14031dfdae4..01a45b0625b25d7ebaf36f11d2cb05c588da78ed 100644 (file)
@@ -15,7 +15,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.78 2002/04/15 05:22:03 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.79 2002/04/27 21:24:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -152,6 +152,7 @@ copy_heap(Oid OIDOldHeap, const char *NewName)
                                                                                  RelationGetNamespace(OldHeap),
                                                                                  tupdesc,
                                                                                  OldHeap->rd_rel->relkind,
+                                                                                 OldHeap->rd_rel->relisshared,
                                                                                  OldHeap->rd_rel->relhasoids,
                                                                                  allowSystemTableMods);
 
index 9b5c47969a489aed2d41ad9d435e06aca03ca3e4..41f122767ad780c20c714009e84280f6d1c1cc93 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.87 2002/04/21 00:26:42 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.88 2002/04/27 21:24:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -475,11 +475,14 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt)
                elog(ERROR, "permission denied");
 
        MemSet(repl_repl, ' ', sizeof(repl_repl));
-
        repl_repl[Anum_pg_database_datconfig-1] = 'r';
+
        if (strcmp(stmt->variable, "all")==0 && stmt->value == NULL)
+       {
                /* RESET ALL */
                repl_null[Anum_pg_database_datconfig-1] = 'n';
+               repl_val[Anum_pg_database_datconfig-1] = (Datum) 0;
+       }
        else
        {
                Datum datum;
@@ -491,16 +494,12 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt)
                datum = heap_getattr(tuple, Anum_pg_database_datconfig,
                                                         RelationGetDescr(rel), &isnull);
 
+               a = isnull ? ((ArrayType *) NULL) : DatumGetArrayTypeP(datum);
+
                if (valuestr)
-                       a = GUCArrayAdd(isnull
-                                                       ? NULL
-                                                       : (ArrayType *) pg_detoast_datum((struct varlena *)datum),
-                                                       stmt->variable, valuestr);
+                       a = GUCArrayAdd(a, stmt->variable, valuestr);
                else
-                       a = GUCArrayDelete(isnull
-                                                          ? NULL
-                                                          : (ArrayType *) pg_detoast_datum((struct varlena *)datum),
-                                                          stmt->variable);
+                       a = GUCArrayDelete(a, stmt->variable);
 
                repl_val[Anum_pg_database_datconfig-1] = PointerGetDatum(a);
        }
@@ -546,8 +545,6 @@ get_db_info(const char *name, Oid *dbIdP, int4 *ownerIdP,
        if (gottuple)
        {
                Form_pg_database dbform = (Form_pg_database) GETSTRUCT(tuple);
-               text       *tmptext;
-               bool            isnull;
 
                /* oid of the database */
                if (dbIdP)
@@ -573,16 +570,21 @@ get_db_info(const char *name, Oid *dbIdP, int4 *ownerIdP,
                /* database path (as registered in pg_database) */
                if (dbpath)
                {
-                       tmptext = DatumGetTextP(heap_getattr(tuple,
-                                                                                                Anum_pg_database_datpath,
-                                                                                         RelationGetDescr(relation),
-                                                                                                &isnull));
+                       Datum           datum;
+                       bool            isnull;
+
+                       datum = heap_getattr(tuple,
+                                                                Anum_pg_database_datpath,
+                                                                RelationGetDescr(relation),
+                                                                &isnull);
                        if (!isnull)
                        {
-                               Assert(VARSIZE(tmptext) - VARHDRSZ < MAXPGPATH);
+                               text       *pathtext = DatumGetTextP(datum);
+                               int                     pathlen = VARSIZE(pathtext) - VARHDRSZ;
 
-                               strncpy(dbpath, VARDATA(tmptext), VARSIZE(tmptext) - VARHDRSZ);
-                               *(dbpath + VARSIZE(tmptext) - VARHDRSZ) = '\0';
+                               Assert(pathlen >= 0 && pathlen < MAXPGPATH);
+                               strncpy(dbpath, VARDATA(pathtext), pathlen);
+                               *(dbpath + pathlen) = '\0';
                        }
                        else
                                strcpy(dbpath, "");
index 32930710c6ed50f25a290479cbe715f80b8d34d5..79b54aa7a5aeb5a92f20da5667647677ab9cc157 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.11 2002/04/27 03:45:01 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.12 2002/04/27 21:24:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -200,6 +200,7 @@ DefineRelation(CreateStmt *stmt, char relkind)
                                                                                  namespaceId,
                                                                                  descriptor,
                                                                                  relkind,
+                                                                                 false,
                                                                                  stmt->hasoids || parentHasOids,
                                                                                  allowSystemTableMods);
 
@@ -2840,6 +2841,7 @@ AlterTableCreateToastTable(Oid relOid, bool silent)
        HeapTuple       reltup;
        HeapTupleData classtuple;
        TupleDesc       tupdesc;
+       bool            shared_relation;
        Relation        class_rel;
        Buffer          buffer;
        Relation        ridescs[Num_pg_class_indices];
@@ -2856,6 +2858,7 @@ AlterTableCreateToastTable(Oid relOid, bool silent)
         */
        rel = heap_open(relOid, AccessExclusiveLock);
 
+       /* Check permissions */
        if (rel->rd_rel->relkind != RELKIND_RELATION)
                elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table",
                         RelationGetRelationName(rel));
@@ -2863,6 +2866,19 @@ AlterTableCreateToastTable(Oid relOid, bool silent)
        if (!pg_class_ownercheck(relOid, GetUserId()))
                aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(rel));
 
+       /*
+        * Toast table is shared if and only if its parent is.
+        *
+        * We cannot allow toasting a shared relation after initdb (because
+        * there's no way to mark it toasted in other databases' pg_class).
+        * Unfortunately we can't distinguish initdb from a manually started
+        * standalone backend.  However, we can at least prevent this mistake
+        * under normal multi-user operation.
+        */
+       shared_relation = rel->rd_rel->relisshared;
+       if (shared_relation && IsUnderPostmaster)
+               elog(ERROR, "Shared relations cannot be toasted after initdb");
+
        /*
         * lock the pg_class tuple for update (is that really needed?)
         */
@@ -2962,6 +2978,7 @@ AlterTableCreateToastTable(Oid relOid, bool silent)
                                                                                   PG_TOAST_NAMESPACE,
                                                                                   tupdesc,
                                                                                   RELKIND_TOASTVALUE,
+                                                                                  shared_relation,
                                                                                   false,
                                                                                   true);
 
index 771375b88d63c086b7af2dfad02efa91ed6e8f2e..d906c7c2363e3fb6c481d9bf6c3fe57a3991f961 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.98 2002/04/27 15:30:07 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.99 2002/04/27 21:24:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 extern bool Password_encryption;
 
 static void CheckPgUserAclNotNull(void);
-
+static void UpdateGroupMembership(Relation group_rel, HeapTuple group_tuple,
+                                                                 List *members);
+static IdList *IdListToArray(List *members);
+static List *IdArrayToList(IdList *oldarray);
 
 
 /*
@@ -151,16 +154,11 @@ write_group_file(Relation urel, Relation grel)
                bool            first_user = true;
 
                datum = heap_getattr(tuple, Anum_pg_group_groname, dsc, &isnull);
-               if (isnull)
-                       continue;                       /* ignore NULL groupnames */
-               groname = NameStr(*DatumGetName(datum));
-
-               grolist_datum = heap_getattr(tuple, Anum_pg_group_grolist, dsc, &isnull);
-               /* Ignore NULL group lists */
+               /* ignore NULL groupnames --- shouldn't happen */
                if (isnull)
                        continue;
+               groname = NameStr(*DatumGetName(datum));
 
-               grolist_p = DatumGetIdListP(grolist_datum);
                /*
                 * Check for illegal characters in the group name.
                 */
@@ -171,8 +169,15 @@ write_group_file(Relation urel, Relation grel)
                        continue;
                }
 
+               grolist_datum = heap_getattr(tuple, Anum_pg_group_grolist, dsc, &isnull);
+               /* Ignore NULL group lists */
+               if (isnull)
+                       continue;
+
                /* be sure the IdList is not toasted */
-               /* scan it */
+               grolist_p = DatumGetIdListP(grolist_datum);
+
+               /* scan grolist */
                num = IDLIST_NUM(grolist_p);
                aidp = IDLIST_DAT(grolist_p);
                for (i = 0; i < num; ++i)
@@ -290,8 +295,9 @@ write_user_file(Relation urel)
                int                     i;
 
                datum = heap_getattr(tuple, Anum_pg_shadow_usename, dsc, &isnull);
+               /* ignore NULL usernames (shouldn't happen) */
                if (isnull)
-                       continue;                       /* ignore NULL usernames */
+                       continue;
                usename = NameStr(*DatumGetName(datum));
 
                datum = heap_getattr(tuple, Anum_pg_shadow_passwd, dsc, &isnull);
@@ -516,24 +522,19 @@ CreateUser(CreateUserStmt *stmt)
        while (!user_exists && !sysid_exists &&
                   HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
        {
-               Datum           datum;
-               bool            null;
+               Form_pg_shadow shadow_form = (Form_pg_shadow) GETSTRUCT(tuple);
+               int32           this_sysid;
 
-               datum = heap_getattr(tuple, Anum_pg_shadow_usename,
-                                                        pg_shadow_dsc, &null);
-               Assert(!null);
-               user_exists = (strcmp(NameStr(*DatumGetName(datum)), stmt->user) == 0);
+               user_exists = (strcmp(NameStr(shadow_form->usename), stmt->user) == 0);
 
-               datum = heap_getattr(tuple, Anum_pg_shadow_usesysid,
-                                                        pg_shadow_dsc, &null);
-               Assert(!null);
+               this_sysid = shadow_form->usesysid;
                if (havesysid)                  /* customized id wanted */
-                       sysid_exists = (DatumGetInt32(datum) == sysid);
+                       sysid_exists = (this_sysid == sysid);
                else
                {
                        /* pick 1 + max */
-                       if (DatumGetInt32(datum) > max_id)
-                               max_id = DatumGetInt32(datum);
+                       if (this_sysid > max_id)
+                               max_id = this_sysid;
                }
        }
        heap_endscan(scan);
@@ -551,10 +552,12 @@ CreateUser(CreateUserStmt *stmt)
        /*
         * Build a tuple to insert
         */
+       MemSet(new_record, 0, sizeof(new_record));
+       MemSet(new_record_nulls, ' ', sizeof(new_record_nulls));
+
        new_record[Anum_pg_shadow_usename - 1] =
                DirectFunctionCall1(namein, CStringGetDatum(stmt->user));
        new_record[Anum_pg_shadow_usesysid - 1] = Int32GetDatum(sysid);
-
        AssertState(BoolIsValid(createdb));
        new_record[Anum_pg_shadow_usecreatedb - 1] = BoolGetDatum(createdb);
        new_record[Anum_pg_shadow_usetrace - 1] = BoolGetDatum(false);
@@ -577,20 +580,14 @@ CreateUser(CreateUserStmt *stmt)
                                DirectFunctionCall1(textin, CStringGetDatum(encrypted_password));
                }
        }
+       else
+               new_record_nulls[Anum_pg_shadow_passwd - 1] = 'n';
+
        if (validUntil)
                new_record[Anum_pg_shadow_valuntil - 1] =
                        DirectFunctionCall1(nabstimein, CStringGetDatum(validUntil));
-
-       new_record_nulls[Anum_pg_shadow_usename - 1] = ' ';
-       new_record_nulls[Anum_pg_shadow_usesysid - 1] = ' ';
-
-       new_record_nulls[Anum_pg_shadow_usecreatedb - 1] = ' ';
-       new_record_nulls[Anum_pg_shadow_usetrace - 1] = ' ';
-       new_record_nulls[Anum_pg_shadow_usesuper - 1] = ' ';
-       new_record_nulls[Anum_pg_shadow_usecatupd - 1] = ' ';
-
-       new_record_nulls[Anum_pg_shadow_passwd - 1] = password ? ' ' : 'n';
-       new_record_nulls[Anum_pg_shadow_valuntil - 1] = validUntil ? ' ' : 'n';
+       else
+               new_record_nulls[Anum_pg_shadow_valuntil - 1] = 'n';
 
        new_record_nulls[Anum_pg_shadow_useconfig - 1] = 'n';
 
@@ -651,11 +648,11 @@ AlterUser(AlterUserStmt *stmt)
 {
        Datum           new_record[Natts_pg_shadow];
        char            new_record_nulls[Natts_pg_shadow];
+       char            new_record_repl[Natts_pg_shadow];
        Relation        pg_shadow_rel;
        TupleDesc       pg_shadow_dsc;
        HeapTuple       tuple,
                                new_tuple;
-       bool            null;
        List       *option;
        char       *password = NULL;    /* PostgreSQL user password */
        bool            encrypt_password = Password_encryption; /* encrypt password? */
@@ -749,33 +746,23 @@ AlterUser(AlterUserStmt *stmt)
                elog(ERROR, "ALTER USER: user \"%s\" does not exist", stmt->user);
 
        /*
-        * Build a tuple to update, perusing the information just obtained
+        * Build an updated tuple, perusing the information just obtained
         */
+       MemSet(new_record, 0, sizeof(new_record));
+       MemSet(new_record_nulls, ' ', sizeof(new_record_nulls));
+       MemSet(new_record_repl, ' ', sizeof(new_record_repl));
+
        new_record[Anum_pg_shadow_usename - 1] = DirectFunctionCall1(namein,
                                                                                        CStringGetDatum(stmt->user));
-       new_record_nulls[Anum_pg_shadow_usename - 1] = ' ';
-
-       /* sysid - leave as is */
-       new_record[Anum_pg_shadow_usesysid - 1] = heap_getattr(tuple, Anum_pg_shadow_usesysid, pg_shadow_dsc, &null);
-       new_record_nulls[Anum_pg_shadow_usesysid - 1] = null ? 'n' : ' ';
+       new_record_repl[Anum_pg_shadow_usename - 1] = 'r';
 
        /* createdb */
-       if (createdb < 0)
-       {
-               /* don't change */
-               new_record[Anum_pg_shadow_usecreatedb - 1] = heap_getattr(tuple, Anum_pg_shadow_usecreatedb, pg_shadow_dsc, &null);
-               new_record_nulls[Anum_pg_shadow_usecreatedb - 1] = null ? 'n' : ' ';
-       }
-       else
+       if (createdb >= 0)
        {
                new_record[Anum_pg_shadow_usecreatedb - 1] = BoolGetDatum(createdb > 0);
-               new_record_nulls[Anum_pg_shadow_usecreatedb - 1] = ' ';
+               new_record_repl[Anum_pg_shadow_usecreatedb - 1] = 'r';
        }
 
-       /* trace - leave as is */
-       new_record[Anum_pg_shadow_usetrace - 1] = heap_getattr(tuple, Anum_pg_shadow_usetrace, pg_shadow_dsc, &null);
-       new_record_nulls[Anum_pg_shadow_usetrace - 1] = null ? 'n' : ' ';
-
        /*
         * createuser (superuser) and catupd
         *
@@ -784,22 +771,13 @@ AlterUser(AlterUserStmt *stmt)
         * with a situation where no existing superuser can alter the
         * catalogs, including pg_shadow!
         */
-       if (createuser < 0)
-       {
-               /* don't change */
-               new_record[Anum_pg_shadow_usesuper - 1] = heap_getattr(tuple, Anum_pg_shadow_usesuper, pg_shadow_dsc, &null);
-               new_record_nulls[Anum_pg_shadow_usesuper - 1] = null ? 'n' : ' ';
-
-               new_record[Anum_pg_shadow_usecatupd - 1] = heap_getattr(tuple, Anum_pg_shadow_usecatupd, pg_shadow_dsc, &null);
-               new_record_nulls[Anum_pg_shadow_usecatupd - 1] = null ? 'n' : ' ';
-       }
-       else
+       if (createuser >= 0)
        {
                new_record[Anum_pg_shadow_usesuper - 1] = BoolGetDatum(createuser > 0);
-               new_record_nulls[Anum_pg_shadow_usesuper - 1] = ' ';
+               new_record_repl[Anum_pg_shadow_usesuper - 1] = 'r';
 
                new_record[Anum_pg_shadow_usecatupd - 1] = BoolGetDatum(createuser > 0);
-               new_record_nulls[Anum_pg_shadow_usecatupd - 1] = ' ';
+               new_record_repl[Anum_pg_shadow_usecatupd - 1] = 'r';
        }
 
        /* password */
@@ -816,14 +794,7 @@ AlterUser(AlterUserStmt *stmt)
                        new_record[Anum_pg_shadow_passwd - 1] =
                                DirectFunctionCall1(textin, CStringGetDatum(encrypted_password));
                }
-               new_record_nulls[Anum_pg_shadow_passwd - 1] = ' ';
-       }
-       else
-       {
-               /* leave as is */
-               new_record[Anum_pg_shadow_passwd - 1] =
-                       heap_getattr(tuple, Anum_pg_shadow_passwd, pg_shadow_dsc, &null);
-               new_record_nulls[Anum_pg_shadow_passwd - 1] = null ? 'n' : ' ';
+               new_record_repl[Anum_pg_shadow_passwd - 1] = 'r';
        }
 
        /* valid until */
@@ -831,22 +802,11 @@ AlterUser(AlterUserStmt *stmt)
        {
                new_record[Anum_pg_shadow_valuntil - 1] =
                        DirectFunctionCall1(nabstimein, CStringGetDatum(validUntil));
-               new_record_nulls[Anum_pg_shadow_valuntil - 1] = ' ';
+               new_record_repl[Anum_pg_shadow_valuntil - 1] = 'r';
        }
-       else
-       {
-               /* leave as is */
-               new_record[Anum_pg_shadow_valuntil - 1] =
-                       heap_getattr(tuple, Anum_pg_shadow_valuntil, pg_shadow_dsc, &null);
-               new_record_nulls[Anum_pg_shadow_valuntil - 1] = null ? 'n' : ' ';
-       }
-
-       /* leave useconfig as is */
-       new_record[Anum_pg_shadow_useconfig - 1] =
-               heap_getattr(tuple, Anum_pg_shadow_useconfig, pg_shadow_dsc, &null);
-       new_record_nulls[Anum_pg_shadow_useconfig - 1] = null ? 'n' : ' ';
 
-       new_tuple = heap_formtuple(pg_shadow_dsc, new_record, new_record_nulls);
+       new_tuple = heap_modifytuple(tuple, pg_shadow_rel, new_record,
+                                                                new_record_nulls, new_record_repl);
        simple_heap_update(pg_shadow_rel, &tuple->t_self, new_tuple);
 
        /* Update indexes */
@@ -876,7 +836,6 @@ AlterUser(AlterUserStmt *stmt)
 }
 
 
-
 /*
  * ALTER USER ... SET
  */
@@ -896,6 +855,10 @@ AlterUserSet(AlterUserSetStmt *stmt)
                                ? ((A_Const *) lfirst(stmt->value))->val.val.str
                                : NULL);
 
+       /*
+        * RowExclusiveLock is sufficient, because we don't need to update
+        * the flat password file.
+        */
        rel = heap_openr(ShadowRelationName, RowExclusiveLock);
        oldtuple = SearchSysCache(SHADOWNAME,
                                                          PointerGetDatum(stmt->user),
@@ -925,16 +888,12 @@ AlterUserSet(AlterUserSetStmt *stmt)
                datum = SysCacheGetAttr(SHADOWNAME, oldtuple,
                                                                Anum_pg_shadow_useconfig, &isnull);
 
+               array = isnull ? ((ArrayType *) NULL) : DatumGetArrayTypeP(datum);
+
                if (valuestr)
-                       array = GUCArrayAdd(isnull
-                                                       ? NULL
-                                                       : (ArrayType *) pg_detoast_datum((struct varlena *)datum),
-                                                       stmt->variable, valuestr);
+                       array = GUCArrayAdd(array, stmt->variable, valuestr);
                else
-                       array = GUCArrayDelete(isnull
-                                                          ? NULL
-                                                          : (ArrayType *) pg_detoast_datum((struct varlena *)datum),
-                                                          stmt->variable);
+                       array = GUCArrayDelete(array, stmt->variable);
 
                repl_val[Anum_pg_shadow_useconfig-1] = PointerGetDatum(array);
        }
@@ -982,16 +941,14 @@ DropUser(DropUserStmt *stmt)
 
        foreach(item, stmt->users)
        {
+               const char *user = strVal(lfirst(item));
                HeapTuple       tuple,
                                        tmp_tuple;
                Relation        pg_rel;
                TupleDesc       pg_dsc;
                ScanKeyData scankey;
                HeapScanDesc scan;
-               Datum           datum;
-               bool            null;
                int32           usesysid;
-               const char *user = strVal(lfirst(item));
 
                tuple = SearchSysCache(SHADOWNAME,
                                                           PointerGetDatum(user),
@@ -1000,7 +957,7 @@ DropUser(DropUserStmt *stmt)
                        elog(ERROR, "DROP USER: user \"%s\" does not exist%s", user,
                                 (length(stmt->users) > 1) ? " (no users removed)" : "");
 
-               usesysid = DatumGetInt32(heap_getattr(tuple, Anum_pg_shadow_usesysid, pg_shadow_dsc, &null));
+               usesysid = ((Form_pg_shadow) GETSTRUCT(tuple))->usesysid;
 
                if (usesysid == GetUserId())
                        elog(ERROR, "current user cannot be dropped");
@@ -1028,10 +985,7 @@ DropUser(DropUserStmt *stmt)
                {
                        char       *dbname;
 
-                       datum = heap_getattr(tmp_tuple, Anum_pg_database_datname,
-                                                                pg_dsc, &null);
-                       Assert(!null);
-                       dbname = NameStr(*DatumGetName(datum));
+                       dbname = NameStr(((Form_pg_database) GETSTRUCT(tmp_tuple))->datname);
                        elog(ERROR, "DROP USER: user \"%s\" owns database \"%s\", cannot be removed%s",
                                 user, dbname,
                                 (length(stmt->users) > 1) ? " (no users removed)" : "");
@@ -1066,8 +1020,7 @@ DropUser(DropUserStmt *stmt)
                        AlterGroupStmt ags;
 
                        /* the group name from which to try to drop the user: */
-                       datum = heap_getattr(tmp_tuple, Anum_pg_group_groname, pg_dsc, &null);
-                       ags.name = DatumGetCString(DirectFunctionCall1(nameout, datum));
+                       ags.name = pstrdup(NameStr(((Form_pg_group) GETSTRUCT(tmp_tuple))->groname));
                        ags.action = -1;
                        ags.listUsers = makeList1(makeInteger(usesysid));
                        AlterGroup(&ags, "DROP USER");
@@ -1202,24 +1155,19 @@ CreateGroup(CreateGroupStmt *stmt)
        while (!group_exists && !sysid_exists &&
                   HeapTupleIsValid(tuple = heap_getnext(scan, false)))
        {
-               Datum           datum;
-               bool            null;
+               Form_pg_group group_form = (Form_pg_group) GETSTRUCT(tuple);
+               int32           this_sysid;
 
-               datum = heap_getattr(tuple, Anum_pg_group_groname,
-                                                        pg_group_dsc, &null);
-               Assert(!null);
-               group_exists = (strcmp(NameStr(*DatumGetName(datum)), stmt->name) == 0);
+               group_exists = (strcmp(NameStr(group_form->groname), stmt->name) == 0);
 
-               datum = heap_getattr(tuple, Anum_pg_group_grosysid,
-                                                        pg_group_dsc, &null);
-               Assert(!null);
+               this_sysid = group_form->grosysid;
                if (havesysid)                  /* customized id wanted */
-                       sysid_exists = (DatumGetInt32(datum) == sysid);
+                       sysid_exists = (this_sysid == sysid);
                else
                {
                        /* pick 1 + max */
-                       if (DatumGetInt32(datum) > max_id)
-                               max_id = DatumGetInt32(datum);
+                       if (this_sysid > max_id)
+                               max_id = this_sysid;
                }
        }
        heap_endscan(scan);
@@ -1231,44 +1179,30 @@ CreateGroup(CreateGroupStmt *stmt)
                elog(ERROR, "CREATE GROUP: group sysid %d is already assigned",
                         sysid);
 
+       if (!havesysid)
+               sysid = max_id + 1;
+
        /*
         * Translate the given user names to ids
         */
        foreach(item, userElts)
        {
                const char *groupuser = strVal(lfirst(item));
-               Value      *v;
+               int32           userid = get_usesysid(groupuser);
 
-               v = makeInteger(get_usesysid(groupuser));
-               if (!member(v, newlist))
-                       newlist = lappend(newlist, v);
+               if (!intMember(userid, newlist))
+                       newlist = lappendi(newlist, userid);
        }
 
        /* build an array to insert */
        if (newlist)
-       {
-               int                     i;
-
-               userarray = palloc(ARR_OVERHEAD(1) + length(newlist) * sizeof(int32));
-               userarray->size = ARR_OVERHEAD(1) + length(newlist) * sizeof(int32);
-               userarray->flags = 0;
-               ARR_NDIM(userarray) = 1;        /* one dimensional array */
-               ARR_LBOUND(userarray)[0] = 1;   /* axis starts at one */
-               ARR_DIMS(userarray)[0] = length(newlist);               /* axis is this long */
-               /* fill the array */
-               i = 0;
-               foreach(item, newlist)
-                       ((int *) ARR_DATA_PTR(userarray))[i++] = intVal(lfirst(item));
-       }
+               userarray = IdListToArray(newlist);
        else
                userarray = NULL;
 
        /*
         * Form a tuple to insert
         */
-       if (!havesysid)
-               sysid = max_id + 1;
-
        new_record[Anum_pg_group_groname - 1] =
                DirectFunctionCall1(namein, CStringGetDatum(stmt->name));
        new_record[Anum_pg_group_grosysid - 1] = Int32GetDatum(sysid);
@@ -1318,6 +1252,11 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag)
        Relation        pg_group_rel;
        TupleDesc       pg_group_dsc;
        HeapTuple       group_tuple;
+       IdList     *oldarray;
+       Datum           datum;
+       bool            null;
+       List       *newlist,
+                          *item;
 
        /*
         * Make sure the user can do this.
@@ -1337,6 +1276,14 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag)
        if (!HeapTupleIsValid(group_tuple))
                elog(ERROR, "%s: group \"%s\" does not exist", tag, stmt->name);
 
+       /* Fetch old group membership. */
+       datum = heap_getattr(group_tuple, Anum_pg_group_grolist,
+                                                pg_group_dsc, &null);
+       oldarray = null ? ((IdList *) NULL) : DatumGetIdListP(datum);
+
+       /* initialize list with old array contents */
+       newlist = IdArrayToList(oldarray);
+
        /*
         * Now decide what to do.
         */
@@ -1345,49 +1292,18 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag)
        if (stmt->action == +1)         /* add users, might also be invoked by
                                                                 * create user */
        {
-               Datum           new_record[Natts_pg_group];
-               char            new_record_nulls[Natts_pg_group];
-               ArrayType  *newarray,
-                                  *oldarray;
-               List       *newlist = NIL,
-                                  *item;
-               HeapTuple       tuple;
-               bool            null = false;
-               Datum           datum = heap_getattr(group_tuple, Anum_pg_group_grolist, pg_group_dsc, &null);
-               int                     i;
-
-               oldarray = (ArrayType *) datum;
-               Assert(null || ARR_NDIM(oldarray) == 1);
-               /* first add the old array to the hitherto empty list */
-               if (!null)
-                       for (i = ARR_LBOUND(oldarray)[0]; i < ARR_LBOUND(oldarray)[0] + ARR_DIMS(oldarray)[0]; i++)
-                       {
-                               int                     index,
-                                                       arrval;
-                               Value      *v;
-                               bool            valueNull;
-
-                               index = i;
-                               arrval = DatumGetInt32(array_ref(oldarray, 1, &index, true /* by value */ ,
-                                                                                       sizeof(int), 0, &valueNull));
-                               v = makeInteger(arrval);
-                               /* filter out duplicates */
-                               if (!member(v, newlist))
-                                       newlist = lappend(newlist, v);
-                       }
-
                /*
-                * now convert the to be added usernames to sysids and add them to
+                * convert the to be added usernames to sysids and add them to
                 * the list
                 */
                foreach(item, stmt->listUsers)
                {
-                       Value      *v;
+                       int32   sysid;
 
                        if (strcmp(tag, "ALTER GROUP") == 0)
                        {
                                /* Get the uid of the proposed user to add. */
-                               v = makeInteger(get_usesysid(strVal(lfirst(item))));
+                               sysid = get_usesysid(strVal(lfirst(item)));
                        }
                        else if (strcmp(tag, "CREATE USER") == 0)
                        {
@@ -1395,16 +1311,16 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag)
                                 * in this case we already know the uid and it wouldn't be
                                 * in the cache anyway yet
                                 */
-                               v = lfirst(item);
+                               sysid = intVal(lfirst(item));
                        }
                        else
                        {
                                elog(ERROR, "AlterGroup: unknown tag %s", tag);
-                               v = NULL;               /* keep compiler quiet */
+                               sysid = 0;              /* keep compiler quiet */
                        }
 
-                       if (!member(v, newlist))
-                               newlist = lappend(newlist, v);
+                       if (!intMember(sysid, newlist))
+                               newlist = lappendi(newlist, sysid);
                        else
                                /*
                                 * we silently assume here that this error will only come
@@ -1414,147 +1330,47 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag)
                                         tag, strVal(lfirst(item)), stmt->name);
                }
 
-               newarray = palloc(ARR_OVERHEAD(1) + length(newlist) * sizeof(int32));
-               newarray->size = ARR_OVERHEAD(1) + length(newlist) * sizeof(int32);
-               newarray->flags = 0;
-               ARR_NDIM(newarray) = 1; /* one dimensional array */
-               ARR_LBOUND(newarray)[0] = 1;    /* axis starts at one */
-               ARR_DIMS(newarray)[0] = length(newlist);                /* axis is this long */
-               /* fill the array */
-               i = 0;
-               foreach(item, newlist)
-                       ((int *) ARR_DATA_PTR(newarray))[i++] = intVal(lfirst(item));
-
-               /*
-                * Form a tuple with the new array and write it back.
-                */
-               new_record[Anum_pg_group_groname - 1] =
-                       DirectFunctionCall1(namein, CStringGetDatum(stmt->name));
-               new_record_nulls[Anum_pg_group_groname - 1] = ' ';
-               new_record[Anum_pg_group_grosysid - 1] = heap_getattr(group_tuple, Anum_pg_group_grosysid, pg_group_dsc, &null);
-               new_record_nulls[Anum_pg_group_grosysid - 1] = null ? 'n' : ' ';
-               new_record[Anum_pg_group_grolist - 1] = PointerGetDatum(newarray);
-               new_record_nulls[Anum_pg_group_grolist - 1] = newarray ? ' ' : 'n';
-
-               tuple = heap_formtuple(pg_group_dsc, new_record, new_record_nulls);
-               simple_heap_update(pg_group_rel, &group_tuple->t_self, tuple);
-
-               /* Update indexes */
-               if (RelationGetForm(pg_group_rel)->relhasindex)
-               {
-                       Relation        idescs[Num_pg_group_indices];
-
-                       CatalogOpenIndices(Num_pg_group_indices,
-                                                          Name_pg_group_indices, idescs);
-                       CatalogIndexInsert(idescs, Num_pg_group_indices, pg_group_rel,
-                                                          tuple);
-                       CatalogCloseIndices(Num_pg_group_indices, idescs);
-               }
+               /* Do the update */
+               UpdateGroupMembership(pg_group_rel, group_tuple, newlist);
        }                                                       /* endif alter group add user */
 
        else if (stmt->action == -1)    /* drop users from group */
        {
-               Datum           datum;
-               bool            null;
                bool            is_dropuser = strcmp(tag, "DROP USER") == 0;
 
-               datum = heap_getattr(group_tuple, Anum_pg_group_grolist, pg_group_dsc, &null);
-               if (null)
+               if (newlist == NIL)
                {
                        if (!is_dropuser)
                                elog(WARNING, "ALTER GROUP: group \"%s\" does not have any members", stmt->name);
                }
                else
                {
-                       HeapTuple       tuple;
-                       Datum           new_record[Natts_pg_group];
-                       char            new_record_nulls[Natts_pg_group];
-                       ArrayType  *oldarray,
-                                          *newarray;
-                       List       *newlist = NIL,
-                                          *item;
-                       int                     i;
-
-                       oldarray = (ArrayType *) datum;
-                       Assert(ARR_NDIM(oldarray) == 1);
-                       /* first add the old array to the hitherto empty list */
-                       for (i = ARR_LBOUND(oldarray)[0]; i < ARR_LBOUND(oldarray)[0] + ARR_DIMS(oldarray)[0]; i++)
-                       {
-                               int                     index,
-                                                       arrval;
-                               Value      *v;
-                               bool            valueNull;
-
-                               index = i;
-                               arrval = DatumGetInt32(array_ref(oldarray, 1, &index, true /* by value */ ,
-                                                                                       sizeof(int), 0, &valueNull));
-                               v = makeInteger(arrval);
-                               /* filter out duplicates */
-                               if (!member(v, newlist))
-                                       newlist = lappend(newlist, v);
-                       }
-
                        /*
-                        * now convert the to be dropped usernames to sysids and
+                        * convert the to be dropped usernames to sysids and
                         * remove them from the list
                         */
                        foreach(item, stmt->listUsers)
                        {
-                               Value      *v;
+                               int32           sysid;
 
                                if (!is_dropuser)
                                {
                                        /* Get the uid of the proposed user to drop. */
-                                       v = makeInteger(get_usesysid(strVal(lfirst(item))));
+                                       sysid = get_usesysid(strVal(lfirst(item)));
                                }
                                else
                                {
                                        /* for dropuser we already know the uid */
-                                       v = lfirst(item);
+                                       sysid = intVal(lfirst(item));
                                }
-                               if (member(v, newlist))
-                                       newlist = LispRemove(v, newlist);
+                               if (intMember(sysid, newlist))
+                                       newlist = lremovei(sysid, newlist);
                                else if (!is_dropuser)
                                        elog(WARNING, "ALTER GROUP: user \"%s\" is not in group \"%s\"", strVal(lfirst(item)), stmt->name);
                        }
 
-                       newarray = palloc(ARR_OVERHEAD(1) + length(newlist) * sizeof(int32));
-                       newarray->size = ARR_OVERHEAD(1) + length(newlist) * sizeof(int32);
-                       newarray->flags = 0;
-                       ARR_NDIM(newarray) = 1;         /* one dimensional array */
-                       ARR_LBOUND(newarray)[0] = 1;            /* axis starts at one */
-                       ARR_DIMS(newarray)[0] = length(newlist);        /* axis is this long */
-                       /* fill the array */
-                       i = 0;
-                       foreach(item, newlist)
-                               ((int *) ARR_DATA_PTR(newarray))[i++] = intVal(lfirst(item));
-
-                       /*
-                        * Insert the new tuple with the updated user list
-                        */
-                       new_record[Anum_pg_group_groname - 1] =
-                               DirectFunctionCall1(namein, CStringGetDatum(stmt->name));
-                       new_record_nulls[Anum_pg_group_groname - 1] = ' ';
-                       new_record[Anum_pg_group_grosysid - 1] = heap_getattr(group_tuple, Anum_pg_group_grosysid, pg_group_dsc, &null);
-                       new_record_nulls[Anum_pg_group_grosysid - 1] = null ? 'n' : ' ';
-                       new_record[Anum_pg_group_grolist - 1] = PointerGetDatum(newarray);
-                       new_record_nulls[Anum_pg_group_grolist - 1] = newarray ? ' ' : 'n';
-
-                       tuple = heap_formtuple(pg_group_dsc, new_record, new_record_nulls);
-                       simple_heap_update(pg_group_rel, &group_tuple->t_self, tuple);
-
-                       /* Update indexes */
-                       if (RelationGetForm(pg_group_rel)->relhasindex)
-                       {
-                               Relation        idescs[Num_pg_group_indices];
-
-                               CatalogOpenIndices(Num_pg_group_indices,
-                                                                  Name_pg_group_indices, idescs);
-                               CatalogIndexInsert(idescs, Num_pg_group_indices, pg_group_rel,
-                                                                  tuple);
-                               CatalogCloseIndices(Num_pg_group_indices, idescs);
-                       }
-
+                       /* Do the update */
+                       UpdateGroupMembership(pg_group_rel, group_tuple, newlist);
                }                                               /* endif group not null */
        }                                                       /* endif alter group drop user */
 
@@ -1571,6 +1387,107 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag)
        update_pg_pwd_and_pg_group(NULL);
 }
 
+/*
+ * Subroutine for AlterGroup: given a pg_group tuple and a desired new
+ * membership (expressed as an integer list), form and write an updated tuple.
+ * The pg_group relation must be open and locked already.
+ */
+static void
+UpdateGroupMembership(Relation group_rel, HeapTuple group_tuple,
+                                         List *members)
+{
+       IdList     *newarray;
+       Datum           new_record[Natts_pg_group];
+       char            new_record_nulls[Natts_pg_group];
+       char            new_record_repl[Natts_pg_group];
+       HeapTuple       tuple;
+
+       newarray = IdListToArray(members);
+
+       /*
+        * Form an updated tuple with the new array and write it back.
+        */
+       MemSet(new_record, 0, sizeof(new_record));
+       MemSet(new_record_nulls, ' ', sizeof(new_record_nulls));
+       MemSet(new_record_repl, ' ', sizeof(new_record_repl));
+
+       new_record[Anum_pg_group_grolist - 1] = PointerGetDatum(newarray);
+       new_record_repl[Anum_pg_group_grolist - 1] = 'r';
+
+       tuple = heap_modifytuple(group_tuple, group_rel,
+                                                        new_record, new_record_nulls, new_record_repl);
+
+       simple_heap_update(group_rel, &group_tuple->t_self, tuple);
+
+       /* Update indexes */
+       if (RelationGetForm(group_rel)->relhasindex)
+       {
+               Relation        idescs[Num_pg_group_indices];
+
+               CatalogOpenIndices(Num_pg_group_indices,
+                                                  Name_pg_group_indices, idescs);
+               CatalogIndexInsert(idescs, Num_pg_group_indices, group_rel,
+                                                  tuple);
+               CatalogCloseIndices(Num_pg_group_indices, idescs);
+       }
+}
+
+
+/*
+ * Convert an integer list of sysids to an array.
+ */
+static IdList *
+IdListToArray(List *members)
+{
+       int                     nmembers = length(members);
+       IdList     *newarray;
+       List       *item;
+       int                     i;
+
+       newarray = palloc(ARR_OVERHEAD(1) + nmembers * sizeof(int32));
+       newarray->size = ARR_OVERHEAD(1) + nmembers * sizeof(int32);
+       newarray->flags = 0;
+       ARR_NDIM(newarray) = 1;         /* one dimensional array */
+       ARR_LBOUND(newarray)[0] = 1;    /* axis starts at one */
+       ARR_DIMS(newarray)[0] = nmembers; /* axis is this long */
+       i = 0;
+       foreach(item, members)
+       {
+               ((int *) ARR_DATA_PTR(newarray))[i++] = lfirsti(item);
+       }
+
+       return newarray;
+}
+
+/*
+ * Convert an array of sysids to an integer list.
+ */
+static List *
+IdArrayToList(IdList *oldarray)
+{
+       List       *newlist = NIL;
+       int                     hibound,
+                               i;
+
+       if (oldarray == NULL)
+               return NIL;
+
+       Assert(ARR_NDIM(oldarray) == 1);
+
+       hibound = ARR_DIMS(oldarray)[0];
+
+       for (i = 0; i < hibound; i++)
+       {
+               int32           sysid;
+
+               sysid = ((int *) ARR_DATA_PTR(oldarray))[i];
+               /* filter out any duplicates --- probably a waste of time */
+               if (!intMember(sysid, newlist))
+                       newlist = lappendi(newlist, sysid);
+       }
+
+       return newlist;
+}
 
 
 /*
@@ -1580,10 +1497,7 @@ void
 DropGroup(DropGroupStmt *stmt)
 {
        Relation        pg_group_rel;
-       HeapScanDesc scan;
        HeapTuple       tuple;
-       TupleDesc       pg_group_dsc;
-       bool            gro_exists = false;
 
        /*
         * Make sure the user can do this.
@@ -1592,34 +1506,18 @@ DropGroup(DropGroupStmt *stmt)
                elog(ERROR, "DROP GROUP: permission denied");
 
        /*
-        * Scan the pg_group table and delete all matching groups.
+        * Drop the group.
         */
        pg_group_rel = heap_openr(GroupRelationName, ExclusiveLock);
-       pg_group_dsc = RelationGetDescr(pg_group_rel);
-       scan = heap_beginscan(pg_group_rel, false, SnapshotNow, 0, NULL);
 
-       while (HeapTupleIsValid(tuple = heap_getnext(scan, false)))
-       {
-               Datum           datum;
-               bool            null;
-
-               datum = heap_getattr(tuple, Anum_pg_group_groname,
-                                                        pg_group_dsc, &null);
-               if (!null && strcmp(NameStr(*DatumGetName(datum)), stmt->name) == 0)
-               {
-                       gro_exists = true;
-                       simple_heap_delete(pg_group_rel, &tuple->t_self);
-               }
-       }
-
-       heap_endscan(scan);
-
-       /*
-        * Did we find any?
-        */
-       if (!gro_exists)
+       tuple = SearchSysCacheCopy(GRONAME,
+                                                          PointerGetDatum(stmt->name),
+                                                          0, 0, 0);
+       if (!HeapTupleIsValid(tuple))
                elog(ERROR, "DROP GROUP: group \"%s\" does not exist", stmt->name);
 
+       simple_heap_delete(pg_group_rel, &tuple->t_self);
+
        heap_close(pg_group_rel, NoLock);
 
        /*
index da12fa9a1db476aa8dffce2ce051b6fa2c238969..68fcb325a63666a4e4029301d3fe635b7dc97571 100644 (file)
@@ -27,7 +27,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.159 2002/04/27 03:45:02 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.160 2002/04/27 21:24:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -733,6 +733,7 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
                                                                                         namespaceId,
                                                                                         tupdesc,
                                                                                         RELKIND_RELATION,
+                                                                                        false,
                                                                                         true,
                                                                                         allowSystemTableMods);
 
index 983055ef783cdf54a13fbb6fecc5aa844ef3df98..66954ff8162638a47da99308f68e4403b96628b9 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.162 2002/04/19 16:36:08 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.163 2002/04/27 21:24:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1319,7 +1319,10 @@ LookupOpclassInfo(Oid operatorClassOid,
  *             The relation descriptor is built just from the supplied parameters,
  *             without actually looking at any system table entries.  We cheat
  *             quite a lot since we only need to work for a few basic system
- *             catalogs...
+ *             catalogs.
+ *
+ * formrdesc is currently used for: pg_class, pg_attribute, pg_proc,
+ * and pg_type (see RelationCacheInitialize).
  *
  * Note that these catalogs can't have constraints, default values,
  * rules, or triggers, since we don't cope with any of that.
@@ -1374,9 +1377,10 @@ formrdesc(const char *relationName,
        /*
         * It's important to distinguish between shared and non-shared
         * relations, even at bootstrap time, to make sure we know where they
-        * are stored.
+        * are stored.  At present, all relations that formrdesc is used for
+        * are not shared.
         */
-       relation->rd_rel->relisshared = IsSharedSystemRelationName(relationName);
+       relation->rd_rel->relisshared = false;
 
        relation->rd_rel->relpages = 1;
        relation->rd_rel->reltuples = 1;
@@ -1434,15 +1438,8 @@ formrdesc(const char *relationName,
        /* In bootstrap mode, we have no indexes */
        if (!IsBootstrapProcessingMode())
        {
-               /*
-                * This list is incomplete, but it only has to work for the set of
-                * rels that formrdesc is used for ...
-                */
-               if (strcmp(relationName, RelationRelationName) == 0 ||
-                       strcmp(relationName, AttributeRelationName) == 0 ||
-                       strcmp(relationName, ProcedureRelationName) == 0 ||
-                       strcmp(relationName, TypeRelationName) == 0)
-                       relation->rd_rel->relhasindex = true;
+               /* Otherwise, all the rels formrdesc is used for have indexes */
+               relation->rd_rel->relhasindex = true;
        }
 
        /*
index 4572a8f05e0eafbf9e0c6e3a85d6ae831cfaff1f..a73822e8fe292e8943a4a9ecb239f8dabc01a10e 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/init/globals.c,v 1.63 2002/03/02 21:39:33 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/init/globals.c,v 1.64 2002/04/27 21:24:34 tgl Exp $
  *
  * NOTES
  *       Globals used all over the place should be declared here and not
  */
 #include "postgres.h"
 
-#include <fcntl.h>
-#include <sys/file.h>
-#include <sys/types.h>
-#include <math.h>
-#include <unistd.h>
-
-#include "catalog/catname.h"
-#include "catalog/indexing.h"
 #include "libpq/pqcomm.h"
 #include "miscadmin.h"
 #include "storage/backendid.h"
@@ -47,14 +39,11 @@ struct Port *MyProcPort;
 long           MyCancelKey;
 
 char      *DataDir = NULL;
-
  /*
   * The PGDATA directory user says to use, or defaults to via environment
   * variable.  NULL if no option given and no environment variable set
   */
 
-Relation       reldesc;                        /* current relation descriptor */
-
 char           OutputFileName[MAXPGPATH];
 
 char           pg_pathname[MAXPGPATH];         /* full path to postgres
@@ -85,27 +74,3 @@ bool         allowSystemTableMods = false;
 int                    SortMem = 512;
 int                    VacuumMem = 8192;
 int                    NBuffers = DEF_NBUFFERS;
-
-
-/* ----------------
- * List of relations that are shared across all databases in an installation.
- *
- * This used to be binary-searched, requiring that it be kept in sorted order.
- * We just do a linear search now so there's no requirement that the list
- * be ordered. The list is so small it shouldn't make much difference.
- * make sure the list is null-terminated
- *                             - jolly 8/19/95
- * ----------------
- */
-char      *SharedSystemRelationNames[] = {
-       DatabaseRelationName,
-       DatabaseNameIndex,
-       DatabaseOidIndex,
-       GroupRelationName,
-       GroupNameIndex,
-       GroupSysidIndex,
-       ShadowRelationName,
-       ShadowNameIndex,
-       ShadowSysidIndex,
-       NULL
-};
index 9ef8b1c87c54a15b1c210bf35853fd575f4ffde0..c112f1a44ba93f184a5882b19447779d3775e620 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.86 2002/04/04 04:25:49 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.87 2002/04/27 21:24:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -612,9 +612,8 @@ InitializeSessionUserId(const char *username)
                                                        Anum_pg_shadow_useconfig, &isnull);
        if (!isnull)
        {
-               ArrayType *a;
+               ArrayType *a = DatumGetArrayTypeP(datum);
 
-               a = (ArrayType *) pg_detoast_datum((struct varlena *)datum);
                ProcessGUCArray(a, PGC_S_USER);
        }
 
index 0d36d70bea8f9bd2db28ae1716a5a6270e02358e..a2d9758cc14598c27a1162472939122a51fa41ac 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.102 2002/04/01 03:34:26 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.103 2002/04/27 21:24:34 tgl Exp $
  *
  *
  *-------------------------------------------------------------------------
@@ -138,7 +138,7 @@ ReverifyMyDatabase(const char *name)
 #endif
 
        /*
-        * Set up datbase-specific configuration variables.
+        * Set up database-specific configuration variables.
         */
        if (IsUnderPostmaster)
        {
@@ -149,9 +149,8 @@ ReverifyMyDatabase(const char *name)
                                                         RelationGetDescr(pgdbrel), &isnull);
                if (!isnull)
                {
-                       ArrayType *a;
+                       ArrayType *a = DatumGetArrayTypeP(datum);
 
-                       a = (ArrayType *) pg_detoast_datum((struct varlena *)datum);
                        ProcessGUCArray(a, PGC_S_DATABASE);
                }
        }
index 195e4f8a83cc0361304e16743d35e3522b5a539f..9a6b78217b784273b11285a99caa8f861bb4a1b5 100644 (file)
@@ -27,7 +27,7 @@
 # Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
 # Portions Copyright (c) 1994, Regents of the University of California
 #
-# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.151 2002/04/21 00:26:43 tgl Exp $
+# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.152 2002/04/27 21:24:34 tgl Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -658,10 +658,13 @@ $ECHO_N "enabling unlimited row size for system tables... "$ECHO_C
 
 "$PGPATH"/postgres $PGSQL_OPT template1 >/dev/null <<EOF
 ALTER TABLE pg_attrdef CREATE TOAST TABLE;
+ALTER TABLE pg_database CREATE TOAST TABLE;
 ALTER TABLE pg_description CREATE TOAST TABLE;
+ALTER TABLE pg_group CREATE TOAST TABLE;
 ALTER TABLE pg_proc CREATE TOAST TABLE;
 ALTER TABLE pg_relcheck CREATE TOAST TABLE;
 ALTER TABLE pg_rewrite CREATE TOAST TABLE;
+ALTER TABLE pg_shadow CREATE TOAST TABLE;
 ALTER TABLE pg_statistic CREATE TOAST TABLE;
 EOF
 if [ "$?" -ne 0 ]; then
index a2e3a0df193f2b13cdfcda569f27388d4b4d50ac..49e91004e94b7014bf798c6b32fe93c81154d7c5 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: bootstrap.h,v 1.28 2002/03/26 19:16:20 tgl Exp $
+ * $Id: bootstrap.h,v 1.29 2002/04/27 21:24:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -31,7 +31,7 @@ typedef struct hashnode
 } hashnode;
 
 
-extern Relation reldesc;
+extern Relation boot_reldesc;
 extern Form_pg_attribute attrtypes[MAXATTR];
 extern int     numattr;
 extern int     BootstrapMain(int ac, char *av[]);
index 255bb265c4c64ffcd9b0b02c86281fcdef1711eb..1a92b5e32e66662c60fc1e80ebe8e8ca7b587669 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: catalog.h,v 1.23 2002/04/12 20:38:30 tgl Exp $
+ * $Id: catalog.h,v 1.24 2002/04/27 21:24:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -30,7 +30,6 @@ extern bool IsSystemNamespace(Oid namespaceId);
 extern bool IsToastNamespace(Oid namespaceId);
 
 extern bool IsReservedName(const char *name);
-extern bool IsSharedSystemRelationName(const char *relname);
 
 extern Oid     newoid(void);
 
index bf3bf789756997d868aa0c9df1bd542e35a8ede7..510529463963259199c07b9fb56a997d487cd507 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: catname.h,v 1.24 2002/03/22 21:34:44 tgl Exp $
+ * $Id: catname.h,v 1.25 2002/04/27 21:24:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -42,6 +42,4 @@
 #define  RelCheckRelationName "pg_relcheck"
 #define  TriggerRelationName "pg_trigger"
 
-extern char *SharedSystemRelationNames[];
-
 #endif   /* CATNAME_H */
index cf718933365dbaa80c18209fbfcd9d19f221f01f..6ebe79cc6a3d5ce09cccfc83abe3aa2480284125 100644 (file)
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: catversion.h,v 1.127 2002/04/26 01:24:08 tgl Exp $
+ * $Id: catversion.h,v 1.128 2002/04/27 21:24:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     200204251
+#define CATALOG_VERSION_NO     200204271
 
 #endif
index a0ab4c708a7c75c0eebfa48130991c2c126328c8..2a81f5b26019e64db0f0bfb105685fdb5cb997b6 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: heap.h,v 1.49 2002/03/31 06:26:32 tgl Exp $
+ * $Id: heap.h,v 1.50 2002/04/27 21:24:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -30,6 +30,7 @@ typedef struct RawColumnDefault
 extern Relation heap_create(const char *relname,
                        Oid relnamespace,
                        TupleDesc tupDesc,
+                       bool shared_relation,
                        bool storage_create,
                        bool allow_system_table_mods);
 
@@ -39,6 +40,7 @@ extern Oid heap_create_with_catalog(const char *relname,
                                                 Oid relnamespace,
                                                 TupleDesc tupdesc,
                                                 char relkind,
+                                                bool shared_relation,
                                                 bool relhasoids,
                                                 bool allow_system_table_mods);
 
index 3e7c08dc214636b676d34c57266b165511152aa4..c86f738d87a8fc065dd87a2233bc69003cbf2832 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_database.h,v 1.23 2002/04/21 00:26:43 tgl Exp $
+ * $Id: pg_database.h,v 1.24 2002/04/27 21:24:34 tgl Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
@@ -31,7 +31,7 @@
  *             typedef struct FormData_pg_database
  * ----------------
  */
-CATALOG(pg_database) BOOTSTRAP
+CATALOG(pg_database) BOOTSTRAP BKI_SHARED_RELATION
 {
        NameData        datname;                /* database name */
        int4            datdba;                 /* sysid of owner */
index e64cb3f3964e87b9f42453ee0aab4db81c14c775..d240dfe8041f3c376d986bafdcca10efeb75e212 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_group.h,v 1.13 2001/11/05 17:46:32 momjian Exp $
+ * $Id: pg_group.h,v 1.14 2002/04/27 21:24:34 tgl Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
@@ -25,7 +25,7 @@
  * ----------------
  */
 
-CATALOG(pg_group) BOOTSTRAP BKI_WITHOUT_OIDS
+CATALOG(pg_group) BOOTSTRAP BKI_SHARED_RELATION BKI_WITHOUT_OIDS
 {
        NameData        groname;
        int4            grosysid;
index fd372ae7bf47592395553b715a1b42756ce32656..a46790b353ea07bd8552ff7d164350536900e0a8 100644 (file)
@@ -9,7 +9,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_shadow.h,v 1.19 2002/04/11 05:32:03 petere Exp $
+ * $Id: pg_shadow.h,v 1.20 2002/04/27 21:24:34 tgl Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
@@ -29,7 +29,7 @@
  *             typedef struct FormData_pg_shadow
  * ----------------
  */
-CATALOG(pg_shadow) BOOTSTRAP BKI_WITHOUT_OIDS
+CATALOG(pg_shadow) BOOTSTRAP BKI_SHARED_RELATION BKI_WITHOUT_OIDS
 {
        NameData        usename;
        int4            usesysid;
@@ -37,8 +37,9 @@ CATALOG(pg_shadow) BOOTSTRAP BKI_WITHOUT_OIDS
        bool            usetrace;
        bool            usesuper;               /* read this field via superuser() only */
        bool            usecatupd;
+       /* remaining fields may be null; use heap_getattr to read them! */
        text            passwd;
-       int4            valuntil;
+       int4            valuntil;               /* actually abstime */
        text            useconfig[1];
 } FormData_pg_shadow;
 
index cc647c2d2dbc9984ffb559fdc286d429df00c4ae..4fd2fd9bbdcdf3a83ef01caf8dcfed7697ad28b6 100644 (file)
@@ -10,7 +10,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1995, Regents of the University of California
  *
- * $Id: postgres.h,v 1.56 2001/11/05 17:46:31 momjian Exp $
+ * $Id: postgres.h,v 1.57 2002/04/27 21:24:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -597,7 +597,7 @@ extern int  assertTest(int val);
 #define CATALOG(x)     typedef struct CppConcat(FormData_,x)
 
 #define BOOTSTRAP
-
+#define BKI_SHARED_RELATION
 #define BKI_WITHOUT_OIDS
 
 /* these need to expand into some harmless, repeatable declaration */