OSDN Git Service

I've created a new shared catalog table pg_shdescription to store
authorBruce Momjian <bruce@momjian.us>
Sun, 12 Feb 2006 03:22:21 +0000 (03:22 +0000)
committerBruce Momjian <bruce@momjian.us>
Sun, 12 Feb 2006 03:22:21 +0000 (03:22 +0000)
comments on cluster global objects like databases, tablespaces, and
roles.

It touches a lot of places, but not much in the way of big changes.  The
only design decision I made was to duplicate the query and manipulation
functions rather than to try and have them handle both shared and local
comments.  I believe this is simpler for the code and not an issue for
callers because they know what type of object they are dealing with.
This has resulted in a shobj_description function analagous to
obj_description and backend functions [Create/Delete]SharedComments
mirroring the existing [Create/Delete]Comments functions.

pg_shdescription.h goes into src/include/catalog/

Kris Jurka

25 files changed:
doc/src/sgml/catalogs.sgml
doc/src/sgml/func.sgml
doc/src/sgml/ref/comment.sgml
src/backend/catalog/Makefile
src/backend/catalog/genbki.sh
src/backend/commands/comment.c
src/backend/commands/dbcommands.c
src/backend/commands/tablespace.c
src/backend/commands/user.c
src/backend/parser/gram.y
src/bin/initdb/initdb.c
src/bin/pg_dump/pg_dump.c
src/bin/pg_dump/pg_dumpall.c
src/bin/psql/command.c
src/bin/psql/describe.c
src/bin/psql/describe.h
src/bin/psql/tab-complete.c
src/include/catalog/catversion.h
src/include/catalog/indexing.h
src/include/catalog/pg_database.h
src/include/catalog/pg_proc.h
src/include/catalog/pg_shdescription.h [new file with mode: 0644]
src/include/commands/comment.h
src/include/postgres.h
src/test/regress/expected/sanity_check.out

index d9fd64f..69c8213 100644 (file)
@@ -1,6 +1,6 @@
 <!--
  Documentation of the system catalogs, directed toward PostgreSQL developers
- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.119 2006/01/21 19:05:59 tgl Exp $
+ $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.120 2006/02/12 03:22:16 momjian Exp $
  -->
 
 <chapter id="catalogs">
      </row>
 
      <row>
+      <entry><link linkend="catalog-pg-shdescription"><structname>pg_shdescription</structname></link></entry>
+      <entry>comments on shared objects</entry>
+     </row>
+
+     <row>
       <entry><link linkend="catalog-pg-statistic"><structname>pg_statistic</structname></link></entry>
       <entry>planner statistics</entry>
      </row>
    contents of <structname>pg_description</structname>.
   </para>
 
+  <para>
+   See also <link linkend="catalog-pg-shdescription"><structname>pg_shdescription</structname></link>,
+   which performs a similar function for descriptions involving objects that
+   are shared across a database cluster.
+  </para>
+
   <table>
    <title><structname>pg_description</> Columns</title>
 
 
  </sect1>
 
+ <sect1 id="catalog-pg-shdescription">
+  <title><structname>pg_shdescription</structname></title>
+
+  <indexterm zone="catalog-pg-shdescription">
+   <primary>pg_shdescription</primary>
+  </indexterm>
+
+  <para>
+   The catalog <structname>pg_shdescription</structname> stores optional
+   descriptions (comments) for shared database objects.  Descriptions can
+   be manipulated with the <command>COMMENT</command> command and viewed
+   with <application>psql</application>'s <literal>\d</literal> commands.
+  </para>
+
+  <para>
+   See also <link linkend="catalog-pg-description"><structname>pg_description</structname></link>,
+   which performs a similar function for descriptions involving objects
+   within a single database.
+  </para>
+
+  <para>
+   Unlike most system catalogs, <structname>pg_shdescription</structname>
+   is shared across all databases of a cluster: there is only one
+   copy of <structname>pg_shdescription</structname> per cluster, not
+   one per database.
+  </para>
+
+  <table>
+   <title><structname>pg_shdescription</> Columns</title>
+
+   <tgroup cols=4>
+    <thead>
+     <row>
+      <entry>Name</entry>
+      <entry>Type</entry>
+      <entry>References</entry>
+      <entry>Description</entry>
+     </row>
+    </thead>
+
+    <tbody>
+     <row>
+      <entry><structfield>objoid</structfield></entry>
+      <entry><type>oid</type></entry>
+      <entry>any OID column</entry>
+      <entry>The OID of the object this description pertains to</entry>
+     </row>
+
+     <row>
+      <entry><structfield>classoid</structfield></entry>
+      <entry><type>oid</type></entry>
+      <entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.oid</literal></entry>
+      <entry>The OID of the system catalog this object appears in</entry>
+     </row>
+
+     <row>
+      <entry><structfield>description</structfield></entry>
+      <entry><type>text</type></entry>
+      <entry></entry>
+      <entry>Arbitrary text that servers as the description of this object.</entry>
+     </row>
+    </tbody>
+   </tgroup>
+  </table>
+
+ </sect1>
+
 
  <sect1 id="catalog-pg-statistic">
   <title><structname>pg_statistic</structname></title>
index e2c27e1..addf2ee 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.304 2006/02/11 03:32:38 momjian Exp $
+$PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.305 2006/02/12 03:22:16 momjian Exp $
 PostgreSQL documentation
 -->
 
@@ -9464,6 +9464,10 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
    </indexterm>
 
    <indexterm zone="functions-info">
+    <primary>shobj_description</primary>
+   </indexterm>
+
+   <indexterm zone="functions-info">
     <primary>comment</primary>
     <secondary sortas="database objects">about database objects</secondary>
    </indexterm>
@@ -9499,6 +9503,11 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
        <entry><type>text</type></entry>
        <entry>get comment for a table column</entry>
       </row>
+      <row>
+       <entry><literal><function>shobj_description</function>(<parameter>object_oid</parameter>, <parameter>catalog_name</parameter>)</literal></entry>
+       <entry><type>text</type></entry>
+       <entry>get comment for a shared database object</entry>
+      </row>
      </tbody>
     </tgroup>
    </table>
@@ -9521,6 +9530,14 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
     <function>obj_description</function> cannot be used for table columns since
     columns do not have OIDs of their own.
    </para>
+
+   <para>
+    <function>shobj_description</function> is used just like
+    <function>obj_description</function> only that it is used for retrieving
+    comments on shared objects.  Some system catalogs are global to all
+    databases within each cluster and their descriptions are stored globally
+    as well.
+   </para>
   </sect1>
 
  <sect1 id="functions-admin">
index f3f4251..d8c0a3a 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/comment.sgml,v 1.29 2005/06/08 21:15:27 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/comment.sgml,v 1.30 2006/02/12 03:22:17 momjian Exp $
 PostgreSQL documentation
 -->
 
@@ -36,9 +36,11 @@ COMMENT ON
   OPERATOR <replaceable class="PARAMETER">op</replaceable> (<replaceable class="PARAMETER">leftoperand_type</replaceable>, <replaceable class="PARAMETER">rightoperand_type</replaceable>) |
   OPERATOR CLASS <replaceable class="PARAMETER">object_name</replaceable> USING <replaceable class="parameter">index_method</replaceable> |
   [ PROCEDURAL ] LANGUAGE <replaceable class="PARAMETER">object_name</replaceable> |
+  ROLE <replaceable class="PARAMETER">object_name</replaceable> |
   RULE <replaceable class="PARAMETER">rule_name</replaceable> ON <replaceable class="PARAMETER">table_name</replaceable> |
   SCHEMA <replaceable class="PARAMETER">object_name</replaceable> |
   SEQUENCE <replaceable class="PARAMETER">object_name</replaceable> |
+  TABLESPACE <replaceable class="PARAMETER">object_name</replaceable> |
   TRIGGER <replaceable class="PARAMETER">trigger_name</replaceable> ON <replaceable class="PARAMETER">table_name</replaceable> |
   TYPE <replaceable class="PARAMETER">object_name</replaceable> |
   VIEW <replaceable class="PARAMETER">object_name</replaceable>
@@ -67,7 +69,8 @@ COMMENT ON
     <command>\dd</command>, <command>\d+</command>, and <command>\l+</command>.
     Other user interfaces to retrieve comments can be built atop
     the same built-in functions that <application>psql</application> uses, namely
-    <function>obj_description</> and <function>col_description</>
+    <function>obj_description</>, <function>col_description</>,
+    and <function>shobj_description</> 
     (see <xref linkend="functions-info-comment-table">).
   </para>
  </refsect1>
@@ -198,16 +201,14 @@ COMMENT ON
   <title>Notes</title>
 
   <para>
-   A comment for a database can only be created in that database,
-   and will only be visible in that database, not in other databases.
-  </para>
-
-  <para>
    There is presently no security mechanism for comments: any user
    connected to a database can see all the comments for objects in
    that database (although only superusers can change comments for
-   objects that they don't own).  Therefore, don't put
-   security-critical information in comments.
+   objects that they don't own).  For shared objects such as
+   databases, roles, and tablespaces comments are stored gloablly
+   and any user connected to any database can see all the comments
+   for shared objects.  Therefore, don't put security-critical
+   information in comments.
   </para>
  </refsect1>
 
@@ -245,10 +246,12 @@ COMMENT ON LARGE OBJECT 346344 IS 'Planning document';
 COMMENT ON OPERATOR ^ (text, text) IS 'Performs intersection of two texts';
 COMMENT ON OPERATOR - (NONE, text) IS 'This is a prefix operator on text';
 COMMENT ON OPERATOR CLASS int4ops USING btree IS '4 byte integer operators for btrees';
+COMMENT ON ROLE my_role IS 'Administration group for finance tables';
 COMMENT ON RULE my_rule ON my_table IS 'Logs updates of employee records';
 COMMENT ON SCHEMA my_schema IS 'Departmental data';
 COMMENT ON SEQUENCE my_sequence IS 'Used to generate primary keys';
 COMMENT ON TABLE my_schema.my_table IS 'Employee Information';
+COMMENT ON TABLESPACE my_tablespace IS 'Tablespace for indexes';
 COMMENT ON TRIGGER my_trigger ON my_table IS 'Used for RI';
 COMMENT ON TYPE complex IS 'Complex number data type';
 COMMENT ON VIEW my_view IS 'View of departmental costs';
index 1f52029..635b553 100644 (file)
@@ -2,7 +2,7 @@
 #
 # Makefile for backend/catalog
 #
-# $PostgreSQL: pgsql/src/backend/catalog/Makefile,v 1.58 2005/12/09 21:19:35 petere Exp $
+# $PostgreSQL: pgsql/src/backend/catalog/Makefile,v 1.59 2006/02/12 03:22:17 momjian Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -15,7 +15,7 @@ OBJS = catalog.o dependency.o heap.o index.o indexing.o namespace.o aclchk.o \
        pg_largeobject.o pg_namespace.o pg_operator.o pg_proc.o pg_shdepend.o \
        pg_type.o
 
-BKIFILES = postgres.bki postgres.description
+BKIFILES = postgres.bki postgres.description postgres.shdescription
 
 all: SUBSYS.o $(BKIFILES)
 
@@ -34,7 +34,7 @@ POSTGRES_BKI_SRCS := $(addprefix $(top_srcdir)/src/include/catalog/,\
        pg_rewrite.h pg_trigger.h pg_listener.h pg_description.h pg_cast.h \
        pg_namespace.h pg_conversion.h pg_depend.h \
        pg_database.h pg_tablespace.h pg_pltemplate.h \
-       pg_authid.h pg_auth_members.h pg_shdepend.h \
+       pg_authid.h pg_auth_members.h pg_shdepend.h pg_shdescription.h \
        indexing.h \
     )
 
@@ -43,6 +43,8 @@ pg_includes := $(sort -I$(top_srcdir)/src/include -I$(top_builddir)/src/include)
 # see explanation in ../parser/Makefile
 postgres.description: postgres.bki ;
 
+postgres.shdescription: postgres.bki ;
+
 postgres.bki: genbki.sh $(POSTGRES_BKI_SRCS) \
     $(top_srcdir)/src/include/postgres_ext.h $(top_builddir)/src/include/pg_config_manual.h
        AWK='$(AWK)' $(SHELL) $< $(pg_includes) --set-version=$(VERSION) -o postgres $(POSTGRES_BKI_SRCS)
@@ -51,6 +53,7 @@ postgres.bki: genbki.sh $(POSTGRES_BKI_SRCS) \
 install-data: $(BKIFILES) installdirs
        $(INSTALL_DATA) postgres.bki         '$(DESTDIR)$(datadir)/postgres.bki'
        $(INSTALL_DATA) postgres.description '$(DESTDIR)$(datadir)/postgres.description'
+       $(INSTALL_DATA) postgres.shdescription '$(DESTDIR)$(datadir)/postgres.shdescription'
        $(INSTALL_DATA) $(srcdir)/system_views.sql '$(DESTDIR)$(datadir)/system_views.sql'
        $(INSTALL_DATA) $(srcdir)/information_schema.sql '$(DESTDIR)$(datadir)/information_schema.sql'
        $(INSTALL_DATA) $(srcdir)/sql_features.txt '$(DESTDIR)$(datadir)/sql_features.txt'
index 9d9b75b..4f6b6b2 100644 (file)
@@ -11,7 +11,7 @@
 #
 #
 # IDENTIFICATION
-#    $PostgreSQL: pgsql/src/backend/catalog/genbki.sh,v 1.37 2005/06/28 05:08:52 tgl Exp $
+#    $PostgreSQL: pgsql/src/backend/catalog/genbki.sh,v 1.38 2006/02/12 03:22:17 momjian Exp $
 #
 # NOTES
 #    non-essential whitespace is removed from the generated file.
@@ -103,7 +103,7 @@ fi
 
 TMPFILE="genbkitmp$$.c"
 
-trap "rm -f $TMPFILE ${OUTPUT_PREFIX}.bki.$$ ${OUTPUT_PREFIX}.description.$$" 0 1 2 3 15
+trap "rm -f $TMPFILE ${OUTPUT_PREFIX}.bki.$$ ${OUTPUT_PREFIX}.description.$$ ${OUTPUT_PREFIX}.shdescription.$$" 0 1 2 3 15
 
 
 # Get NAMEDATALEN from postgres_ext.h
@@ -131,6 +131,7 @@ for dir in $INCLUDE_DIRS; do
 done
 
 touch ${OUTPUT_PREFIX}.description.$$
+touch ${OUTPUT_PREFIX}.shdescription.$$
 
 # ----------------
 #      Strip comments and other trash from .h
@@ -201,7 +202,7 @@ comment_level > 0 { next; }
 # ----------------
 #      DATA() statements are basically passed right through after
 #      stripping off the DATA( and the ) on the end.
-#      Remember the OID for use by DESCR().
+#      Remember the OID for use by DESCR() and SHDESCR().
 # ----------------
 /^DATA\(/ {
        data = substr($0, 6, length($0) - 6);
@@ -225,6 +226,16 @@ comment_level > 0 { next; }
        next;
 }
 
+/^SHDESCR\(/ {
+       if (oid != 0)
+       {
+               data = substr($0, 10, length($0) - 11);
+               if (data != "")
+                       printf "%d\t%s\t%s\n", oid, catalog, data >>shdescriptionfile;
+       }
+       next;
+}
+
 /^DECLARE_INDEX\(/ {
 # ----
 #  end any prior catalog data insertions before starting a define index
@@ -365,7 +376,7 @@ END {
                reln_open = 0;
        }
 }
-' "descriptionfile=${OUTPUT_PREFIX}.description.$$" > $TMPFILE || exit
+' "descriptionfile=${OUTPUT_PREFIX}.description.$$" "shdescriptionfile=${OUTPUT_PREFIX}.shdescription.$$" > $TMPFILE || exit
 
 echo "# PostgreSQL $major_version" >${OUTPUT_PREFIX}.bki.$$
 
@@ -386,10 +397,15 @@ if [ `wc -c < ${OUTPUT_PREFIX}.description.$$` -lt 10000 ]; then
     echo "$CMDNAME: something seems to be wrong with the .description file" >&2
     exit 1
 fi
+if [ `wc -c < ${OUTPUT_PREFIX}.shdescription.$$` -lt 10 ]; then
+    echo "$CMDNAME: something seems to be wrong with the .shdescription file" >&2
+    exit 1
+fi
 
 # Looks good, commit ...
 
 mv ${OUTPUT_PREFIX}.bki.$$ ${OUTPUT_PREFIX}.bki || exit
 mv ${OUTPUT_PREFIX}.description.$$ ${OUTPUT_PREFIX}.description || exit
+mv ${OUTPUT_PREFIX}.shdescription.$$ ${OUTPUT_PREFIX}.shdescription || exit
 
 exit 0
index d038542..30b740f 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright (c) 1996-2005, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/comment.c,v 1.85 2005/11/22 18:17:08 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/comment.c,v 1.86 2006/02/12 03:22:17 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -18,6 +18,7 @@
 #include "access/heapam.h"
 #include "catalog/indexing.h"
 #include "catalog/namespace.h"
+#include "catalog/pg_authid.h"
 #include "catalog/pg_cast.h"
 #include "catalog/pg_constraint.h"
 #include "catalog/pg_conversion.h"
 #include "catalog/pg_operator.h"
 #include "catalog/pg_proc.h"
 #include "catalog/pg_rewrite.h"
+#include "catalog/pg_shdescription.h"
+#include "catalog/pg_tablespace.h"
 #include "catalog/pg_trigger.h"
 #include "catalog/pg_type.h"
 #include "commands/comment.h"
 #include "commands/dbcommands.h"
+#include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "parser/parse_func.h"
 #include "parser/parse_oper.h"
@@ -70,6 +74,8 @@ static void CommentLanguage(List *qualname, char *comment);
 static void CommentOpClass(List *qualname, List *arguments, char *comment);
 static void CommentLargeObject(List *qualname, char *comment);
 static void CommentCast(List *qualname, List *arguments, char *comment);
+static void CommentTablespace(List *qualname, char *comment);
+static void CommentRole(List *qualname, char *comment);
 
 
 /*
@@ -134,6 +140,12 @@ CommentObject(CommentStmt *stmt)
                case OBJECT_CAST:
                        CommentCast(stmt->objname, stmt->objargs, stmt->comment);
                        break;
+               case OBJECT_TABLESPACE:
+                       CommentTablespace(stmt->objname, stmt->comment);
+                       break;
+               case OBJECT_ROLE:
+                       CommentRole(stmt->objname, stmt->comment);
+                       break;
                default:
                        elog(ERROR, "unrecognized object type: %d",
                                 (int) stmt->objtype);
@@ -241,6 +253,100 @@ CreateComments(Oid oid, Oid classoid, int32 subid, char *comment)
 }
 
 /*
+ * CreateSharedComments --
+ *
+ * Create a comment for the specified shared object descriptor.  Inserts a
+ * new pg_shdescription tuple, or replaces an existing one with the same key.
+ *
+ * If the comment given is null or an empty string, instead delete any
+ * existing comment for the specified key.
+ */
+void CreateSharedComments(Oid oid, Oid classoid, char *comment)
+{
+       Relation        shdescription;
+       ScanKeyData     skey[2];
+       SysScanDesc     sd;
+       HeapTuple       oldtuple;
+       HeapTuple       newtuple = NULL;
+       Datum           values[Natts_pg_shdescription];
+       char            nulls[Natts_pg_shdescription];
+       char            replaces[Natts_pg_shdescription];
+       int                     i;
+
+       /* Reduce empty-string to NULL case */
+       if (comment != NULL && strlen(comment) == 0)
+               comment = NULL;
+
+       /* Prepare to form or update a tuple, if necessary */
+       if (comment != NULL)
+       {
+               for (i = 0; i < Natts_pg_shdescription; i++)
+               {
+                       nulls[i] = ' ';
+                       replaces[i] = 'r';
+               }
+               i = 0;
+               values[i++] = ObjectIdGetDatum(oid);
+               values[i++] = ObjectIdGetDatum(classoid);
+               values[i++] = DirectFunctionCall1(textin, CStringGetDatum(comment));
+       }
+
+       /* Use the index to search for a matching old tuple */
+
+       ScanKeyInit(&skey[0],
+                       Anum_pg_shdescription_objoid,
+                       BTEqualStrategyNumber, F_OIDEQ,
+                       ObjectIdGetDatum(oid));
+       ScanKeyInit(&skey[1],
+                       Anum_pg_shdescription_classoid,
+                       BTEqualStrategyNumber, F_OIDEQ,
+                       ObjectIdGetDatum(classoid));
+
+       shdescription = heap_open(SharedDescriptionRelationId, RowExclusiveLock);
+
+       sd = systable_beginscan(shdescription, SharedDescriptionObjIndexId, true,
+                       SnapshotNow, 2, skey);
+
+       while ((oldtuple = systable_getnext(sd)) != NULL)
+       {
+               /* Found the old tuple, so delete or update it */
+
+               if (comment == NULL)
+                       simple_heap_delete(shdescription, &oldtuple->t_self);
+               else
+               {
+                       newtuple = heap_modifytuple(oldtuple, RelationGetDescr(shdescription),
+                                       values, nulls, replaces);
+                       simple_heap_update(shdescription, &oldtuple->t_self, newtuple);
+               }
+
+               break;  /* Assume there can be only one match */
+       }
+
+       systable_endscan(sd);
+
+       /* If we didn't find an old tuple, insert a new one */
+
+       if (newtuple == NULL && comment != NULL)
+       {
+               newtuple = heap_formtuple(RelationGetDescr(shdescription),
+                               values, nulls);
+               simple_heap_insert(shdescription, newtuple);
+       }
+
+       /* Update indexes, if necessary */
+       if (newtuple != NULL)
+       {
+               CatalogUpdateIndexes(shdescription, newtuple);
+               heap_freetuple(newtuple);
+       }
+
+       /* Done */
+
+       heap_close(shdescription, NoLock);
+}
+
+/*
  * DeleteComments -- remove comments for an object
  *
  * If subid is nonzero then only comments matching it will be removed.
@@ -293,6 +399,42 @@ DeleteComments(Oid oid, Oid classoid, int32 subid)
 }
 
 /*
+ * DeleteSharedComments -- remove comments for a shared object
+ */
+void
+DeleteSharedComments(Oid oid, Oid classoid)
+{
+       Relation        shdescription;
+       ScanKeyData     skey[2];
+       SysScanDesc     sd;
+       HeapTuple       oldtuple;
+
+       /* Use the index to search for all matching old tuples */
+
+       ScanKeyInit(&skey[0],
+                       Anum_pg_shdescription_objoid,
+                       BTEqualStrategyNumber, F_OIDEQ,
+                       ObjectIdGetDatum(oid));
+       ScanKeyInit(&skey[1],
+                       Anum_pg_shdescription_classoid,
+                       BTEqualStrategyNumber, F_OIDEQ,
+                       ObjectIdGetDatum(classoid));
+
+       shdescription = heap_open(SharedDescriptionRelationId, RowExclusiveLock);
+
+       sd = systable_beginscan(shdescription, SharedDescriptionObjIndexId, true,
+                       SnapshotNow, 2, skey);
+
+       while ((oldtuple = systable_getnext(sd)) != NULL)
+               simple_heap_delete(shdescription, &oldtuple->t_self);
+
+       /* Done */
+
+       systable_endscan(sd);
+       heap_close(shdescription, RowExclusiveLock);
+}
+
+/*
  * CommentRelation --
  *
  * This routine is used to add/drop a comment from a relation, where
@@ -425,7 +567,7 @@ CommentAttribute(List *qualname, char *comment)
  * have regarding the specified database. The routine will check
  * security for owner permissions, and, if successful, will then
  * attempt to find the oid of the database specified. Once found,
- * a comment is added/dropped using the CreateComments() routine.
+ * a comment is added/dropped using the CreateSharedComments() routine.
  */
 static void
 CommentDatabase(List *qualname, char *comment)
@@ -440,11 +582,6 @@ CommentDatabase(List *qualname, char *comment)
        database = strVal(linitial(qualname));
 
        /*
-        * We cannot currently support cross-database comments (since other DBs
-        * cannot see pg_description of this database).  So, we reject attempts to
-        * comment on a database other than the current one. Someday this might be
-        * improved, but it would take a redesigned infrastructure.
-        *
         * When loading a dump, we may see a COMMENT ON DATABASE for the old name
         * of the database.  Erroring out would prevent pg_restore from completing
         * (which is really pg_restore's fault, but for now we will work around
@@ -462,23 +599,83 @@ CommentDatabase(List *qualname, char *comment)
                return;
        }
 
-       /* Only allow comments on the current database */
-       if (oid != MyDatabaseId)
+       /* Check object security */
+       if (!pg_database_ownercheck(oid, GetUserId()))
+               aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
+                                          database);
+
+       /* Call CreateSharedComments() to create/drop the comments */
+       CreateSharedComments(oid, DatabaseRelationId, comment);
+}
+
+/*
+ * CommentTablespace --
+ *
+ * This routine is used to add/drop any user-comments a user might
+ * have regarding a tablespace.  The tablepace is specified by name
+ * and, if found, and the user has appropriate permissions, a
+ * comment will be added/dropped using the CreateSharedComments() routine.
+ *
+ */
+static void
+CommentTablespace(List *qualname, char *comment)
+{
+       char    *tablespace;
+       Oid             oid;
+
+       if (list_length(qualname) != 1)
+               ereport(ERROR,
+                               (errcode(ERRCODE_SYNTAX_ERROR),
+                                errmsg("tablespace name may not be qualified")));
+       tablespace = strVal(linitial(qualname));
+
+       oid = get_tablespace_oid(tablespace);
+       if (!OidIsValid(oid))
        {
-               ereport(WARNING,                /* throw just a warning so pg_restore doesn't
-                                                                * fail */
-                               (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                                errmsg("database comments may only be applied to the current database")));
+               ereport(ERROR,
+                               (errcode(ERRCODE_UNDEFINED_OBJECT),
+                                errmsg("tablespace \"%s\" does not exist", tablespace)));
                return;
        }
 
        /* Check object security */
-       if (!pg_database_ownercheck(oid, GetUserId()))
-               aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
-                                          database);
+       if (!pg_tablespace_ownercheck(oid, GetUserId()))
+               aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TABLESPACE, tablespace);
 
-       /* Call CreateComments() to create/drop the comments */
-       CreateComments(oid, DatabaseRelationId, 0, comment);
+       /* Call CreateSharedComments() to create/drop the comments */
+       CreateSharedComments(oid, TableSpaceRelationId, comment);
+}
+
+/*
+ * CommentRole --
+ *
+ * This routine is used to add/drop any user-comments a user might
+ * have regarding a role.  The role is specified by name
+ * and, if found, and the user has appropriate permissions, a
+ * comment will be added/dropped using the CreateSharedComments() routine.
+ */
+static void
+CommentRole(List *qualname, char *comment)
+{
+       char *role;
+       Oid oid;
+
+       if (list_length(qualname) != 1)
+               ereport(ERROR,
+                               (errcode(ERRCODE_SYNTAX_ERROR),
+                                errmsg("role name may not be qualified")));
+       role = strVal(linitial(qualname));
+
+       oid = get_roleid_checked(role);
+
+       /* Check object security */
+       if (!has_privs_of_role(GetUserId(), oid))
+               ereport(ERROR,
+                               (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+                                errmsg("must be member of role \"%s\" to comment upon it", role)));
+
+       /* Call CreateSharedComments() to create/drop the comments */
+       CreateSharedComments(oid, AuthIdRelationId, comment);
 }
 
 /*
index 5be522d..ea910d7 100644 (file)
@@ -15,7 +15,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.175 2005/11/22 18:17:08 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.176 2006/02/12 03:22:17 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -658,10 +658,8 @@ dropdb(const char *dbname, bool missing_ok)
        /*
         * Delete any comments associated with the database
         *
-        * NOTE: this is probably dead code since any such comments should have
-        * been in that database, not mine.
         */
-       DeleteComments(db_id, DatabaseRelationId, 0);
+       DeleteSharedComments(db_id, DatabaseRelationId);
 
        /*
         * Remove shared dependency references for the database.
index 19955dd..2cca3fa 100644 (file)
@@ -37,7 +37,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.29 2006/01/19 04:45:38 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.30 2006/02/12 03:22:17 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -54,6 +54,7 @@
 #include "catalog/indexing.h"
 #include "catalog/pg_namespace.h"
 #include "catalog/pg_tablespace.h"
+#include "commands/comment.h"
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "storage/fd.h"
@@ -429,6 +430,11 @@ DropTableSpace(DropTableSpaceStmt *stmt)
        heap_endscan(scandesc);
 
        /*
+        * Remove any comments on this tablespace.
+        */
+       DeleteSharedComments(tablespaceoid, TableSpaceRelationId);
+
+       /*
         * Remove dependency on owner.
         */
        deleteSharedDependencyRecordsFor(TableSpaceRelationId, tablespaceoid);
index b3aa2ed..24a5abd 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/backend/commands/user.c,v 1.168 2006/02/04 19:06:46 adunstan Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/user.c,v 1.169 2006/02/12 03:22:17 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -18,6 +18,7 @@
 #include "catalog/indexing.h"
 #include "catalog/pg_auth_members.h"
 #include "catalog/pg_authid.h"
+#include "commands/comment.h"
 #include "commands/user.h"
 #include "libpq/crypt.h"
 #include "miscadmin.h"
@@ -941,6 +942,11 @@ DropRole(DropRoleStmt *stmt)
                systable_endscan(sscan);
 
                /*
+                * Remove any comments on this role.
+                */
+               DeleteSharedComments(roleid, AuthIdRelationId);
+
+               /*
                 * Advance command counter so that later iterations of this loop will
                 * see the changes already made.  This is essential if, for example,
                 * we are trying to drop both a role and one of its direct members ---
index 19270bc..79e4616 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.527 2006/02/11 22:17:18 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.528 2006/02/12 03:22:17 momjian Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -2953,11 +2953,12 @@ TruncateStmt:
  *
  *     COMMENT ON [ [ DATABASE | DOMAIN | INDEX | SEQUENCE | TABLE | TYPE | VIEW |
  *                                CONVERSION | LANGUAGE | OPERATOR CLASS | LARGE OBJECT |
- *                                CAST ] <objname> |
+ *                                CAST | COLUMN | SCHEMA | TABLESPACE | ROLE ] <objname> |
  *                              AGGREGATE <aggname> (<aggtype>) |
  *                              FUNCTION <funcname> (arg1, arg2, ...) |
  *                              OPERATOR <op> (leftoperand_typ, rightoperand_typ) |
  *                              TRIGGER <triggername> ON <relname> |
+ *                              CONSTRAINT <constraintname> ON <relname> |
  *                              RULE <rulename> ON <relname> ]
  *                        IS 'text'
  *
@@ -3088,6 +3089,8 @@ comment_type:
                        | TYPE_P                                                        { $$ = OBJECT_TYPE; }
                        | VIEW                                                          { $$ = OBJECT_VIEW; }
                        | CONVERSION_P                                          { $$ = OBJECT_CONVERSION; }
+                       | TABLESPACE                                            { $$ = OBJECT_TABLESPACE; }
+                       | ROLE                                                          { $$ = OBJECT_ROLE; }
                ;
 
 comment_text:
index 4a85dfb..e1c7ad3 100644 (file)
@@ -42,7 +42,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  * Portions taken from FreeBSD.
  *
- * $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.108 2006/02/10 22:05:42 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.109 2006/02/12 03:22:18 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -105,6 +105,7 @@ static const char *progname;
 static char *encodingid = "0";
 static char *bki_file;
 static char *desc_file;
+static char *shdesc_file;
 static char *hba_file;
 static char *ident_file;
 static char *conf_file;
@@ -181,6 +182,7 @@ static void unlimit_systables(void);
 static void setup_depend(void);
 static void setup_sysviews(void);
 static void setup_description(void);
+static void setup_shared_description(void);
 static void setup_conversion(void);
 static void setup_privileges(void);
 static void set_info_version(void);
@@ -1574,6 +1576,7 @@ unlimit_systables(void)
                "ALTER TABLE pg_description CREATE TOAST TABLE;\n",
                "ALTER TABLE pg_proc CREATE TOAST TABLE;\n",
                "ALTER TABLE pg_rewrite CREATE TOAST TABLE;\n",
+               "ALTER TABLE pg_shdescription CREATE TOAST TABLE;\n",
                "ALTER TABLE pg_statistic CREATE TOAST TABLE;\n",
                NULL
        };
@@ -1752,6 +1755,42 @@ setup_description(void)
 }
 
 /*
+ * load shared description data
+ */
+static void
+setup_shared_description(void)
+{
+       PG_CMD_DECL;
+
+       fputs(_("loading pg_shdescription ... "), stdout);
+       fflush(stdout);
+
+       snprintf(cmd, sizeof(cmd),
+                       "\"%s\" %s template1 >%s",
+                       backend_exec, backend_options,
+                       DEVNULL);
+
+       PG_CMD_OPEN;
+
+       PG_CMD_PUTS("CREATE TEMP TABLE tmp_pg_shdescription ( "
+                       " objoid oid, "
+                       " classname name, "
+                       " description text) WITHOUT OIDS;\n");
+
+       PG_CMD_PRINTF1("COPY tmp_pg_shdescription FROM '%s';\n",
+                       shdesc_file);
+
+       PG_CMD_PUTS("INSERT INTO pg_shdescription "
+                       " SELECT t.objoid, c.oid, t.description "
+                       "  FROM tmp_pg_shdescription t, pg_class c "
+                       "   WHERE c.relname = t.classname;\n");
+
+       PG_CMD_CLOSE;
+
+       check_ok();
+}
+
+/*
  * load conversion functions
  */
 static void
@@ -2702,6 +2741,7 @@ main(int argc, char *argv[])
 
        set_input(&bki_file, "postgres.bki");
        set_input(&desc_file, "postgres.description");
+       set_input(&shdesc_file, "postgres.shdescription");
        set_input(&hba_file, "pg_hba.conf.sample");
        set_input(&ident_file, "pg_ident.conf.sample");
        set_input(&conf_file, "postgresql.conf.sample");
@@ -2718,12 +2758,14 @@ main(int argc, char *argv[])
                                "VERSION=%s\n"
                                "PGDATA=%s\nshare_path=%s\nPGPATH=%s\n"
                                "POSTGRES_SUPERUSERNAME=%s\nPOSTGRES_BKI=%s\n"
-                               "POSTGRES_DESCR=%s\nPOSTGRESQL_CONF_SAMPLE=%s\n"
+                               "POSTGRES_DESCR=%s\nPOSTGRES_SHDESCR=%s\n"
+                               "POSTGRESQL_CONF_SAMPLE=%s\n"
                                "PG_HBA_SAMPLE=%s\nPG_IDENT_SAMPLE=%s\n",
                                PG_VERSION,
                                pg_data, share_path, bin_path,
                                effective_user, bki_file,
-                               desc_file, conf_file,
+                               desc_file, shdesc_file,
+                               conf_file,
                                hba_file, ident_file);
                if (show_setting)
                        exit(0);
@@ -2731,6 +2773,7 @@ main(int argc, char *argv[])
 
        check_input(bki_file);
        check_input(desc_file);
+       check_input(shdesc_file);
        check_input(hba_file);
        check_input(ident_file);
        check_input(conf_file);
@@ -2918,6 +2961,8 @@ main(int argc, char *argv[])
 
        setup_description();
 
+       setup_shared_description();
+
        setup_conversion();
 
        setup_privileges();
index 3dffc9b..fb0be00 100644 (file)
@@ -12,7 +12,7 @@
  *     by PostgreSQL
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.427 2006/01/21 02:16:20 momjian Exp $
+ *       $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.428 2006/02/12 03:22:18 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1185,7 +1185,20 @@ dumpDatabase(Archive *AH)
        selectSourceSchema("pg_catalog");
 
        /* Get the database owner and parameters from pg_database */
-       if (g_fout->remoteVersion >= 80000)
+       if (g_fout->remoteVersion >= 80200)
+       {
+               appendPQExpBuffer(dbQry, "SELECT tableoid, oid, "
+                                                 "(%s datdba) as dba, "
+                                                 "pg_encoding_to_char(encoding) as encoding, "
+                                                 "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) as tablespace, "
+                                                 "shobj_description(oid, 'pg_database') as description "
+
+                                                 "FROM pg_database "
+                                                 "WHERE datname = ",
+                                                 username_subquery);
+               appendStringLiteral(dbQry, datname, true);
+       }
+       else if (g_fout->remoteVersion >= 80000)
        {
                appendPQExpBuffer(dbQry, "SELECT tableoid, oid, "
                                                  "(%s datdba) as dba, "
@@ -1287,10 +1300,28 @@ dumpDatabase(Archive *AH)
                                 NULL);                 /* Dumper Arg */
 
        /* Dump DB comment if any */
-       resetPQExpBuffer(dbQry);
-       appendPQExpBuffer(dbQry, "DATABASE %s", fmtId(datname));
-       dumpComment(AH, dbQry->data, NULL, "",
+       if (g_fout->remoteVersion >= 80200)
+       {
+               /* 8.2 keeps comments on shared objects in a shared table, so
+                * we cannot use the dumpComment used for other database objects.
+                */
+               char *comment = PQgetvalue(res, 0, PQfnumber(res, "description"));
+               if (comment && strlen(comment)) {
+                       resetPQExpBuffer(dbQry);
+                       appendPQExpBuffer(dbQry, "COMMENT ON DATABASE %s IS ", fmtId(datname));
+                       appendStringLiteral(dbQry, comment, false);
+                       appendPQExpBuffer(dbQry, ";\n");
+
+                       ArchiveEntry(AH, dbCatId, createDumpId(), datname, NULL, NULL,
+                                                       dba, false, "COMMENT", dbQry->data, "", NULL,
+                                                       &dbDumpId, 1, NULL, NULL);
+               }
+       } else {
+               resetPQExpBuffer(dbQry);
+               appendPQExpBuffer(dbQry, "DATABASE %s", fmtId(datname));
+               dumpComment(AH, dbQry->data, NULL, "",
                                dbCatId, 0, dbDumpId);
+       }
 
        PQclear(res);
 
index d74e42f..a811b63 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.69 2005/10/15 02:49:39 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.70 2006/02/12 03:22:19 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -409,16 +409,25 @@ dumpRoles(PGconn *conn)
                                i_rolcanlogin,
                                i_rolconnlimit,
                                i_rolpassword,
-                               i_rolvaliduntil;
+                               i_rolvaliduntil,
+                               i_rolcomment;
        int                     i;
 
        /* note: rolconfig is dumped later */
-       if (server_version >= 80100)
+       if (server_version >= 80200)
+               printfPQExpBuffer(buf,
+                                                 "SELECT rolname, rolsuper, rolinherit, "
+                                                 "rolcreaterole, rolcreatedb, rolcatupdate, "
+                                                 "rolcanlogin, rolconnlimit, rolpassword, "
+                                                 "rolvaliduntil, "
+                                                 "pg_catalog.shobj_description(oid, 'pg_authid') as rolcomment "
+                                                 "FROM pg_authid");
+       else if (server_version >= 80100)
                printfPQExpBuffer(buf,
                                                  "SELECT rolname, rolsuper, rolinherit, "
                                                  "rolcreaterole, rolcreatedb, rolcatupdate, "
                                                  "rolcanlogin, rolconnlimit, rolpassword, "
-                                                 "rolvaliduntil "
+                                                 "rolvaliduntil, null as rolcomment "
                                                  "FROM pg_authid");
        else
                printfPQExpBuffer(buf,
@@ -432,6 +441,7 @@ dumpRoles(PGconn *conn)
                                                  "-1 as rolconnlimit, "
                                                  "passwd as rolpassword, "
                                                  "valuntil as rolvaliduntil "
+                                                 "null as rolcomment "
                                                  "FROM pg_shadow "
                                                  "UNION ALL "
                                                  "SELECT groname as rolname, "
@@ -444,6 +454,7 @@ dumpRoles(PGconn *conn)
                                                  "-1 as rolconnlimit, "
                                                  "null::text as rolpassword, "
                                                  "null::abstime as rolvaliduntil "
+                                                 "null "
                                                  "FROM pg_group");
 
        res = executeQuery(conn, buf->data);
@@ -458,6 +469,7 @@ dumpRoles(PGconn *conn)
        i_rolconnlimit = PQfnumber(res, "rolconnlimit");
        i_rolpassword = PQfnumber(res, "rolpassword");
        i_rolvaliduntil = PQfnumber(res, "rolvaliduntil");
+       i_rolcomment = PQfnumber(res, "rolcomment");
 
        if (PQntuples(res) > 0)
                printf("--\n-- Roles\n--\n\n");
@@ -523,6 +535,12 @@ dumpRoles(PGconn *conn)
 
                appendPQExpBuffer(buf, ";\n");
 
+               if (!PQgetisnull(res, i, i_rolcomment)) {
+                       appendPQExpBuffer(buf, "COMMENT ON ROLE %s IS ", fmtId(rolename));
+                       appendStringLiteral(buf, PQgetvalue(res, i, i_rolcomment), true);
+                       appendPQExpBuffer(buf, ";\n");
+               }
+
                printf("%s", buf->data);
 
                if (server_version >= 70300)
@@ -652,9 +670,18 @@ dumpTablespaces(PGconn *conn)
         * Get all tablespaces except built-in ones (which we assume are named
         * pg_xxx)
         */
-       res = executeQuery(conn, "SELECT spcname, "
+       if (server_version >= 80200)
+               res = executeQuery(conn, "SELECT spcname, "
+                                          "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
+                                          "spclocation, spcacl, "
+                                          "pg_catalog.shobj_description(oid, 'pg_tablespace') "
+                                          "FROM pg_catalog.pg_tablespace "
+                                          "WHERE spcname NOT LIKE 'pg!_%' ESCAPE '!'");
+       else 
+               res = executeQuery(conn, "SELECT spcname, "
                                           "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
-                                          "spclocation, spcacl "
+                                          "spclocation, spcacl, "
+                                          "null "
                                           "FROM pg_catalog.pg_tablespace "
                                           "WHERE spcname NOT LIKE 'pg!_%' ESCAPE '!'");
 
@@ -668,6 +695,7 @@ dumpTablespaces(PGconn *conn)
                char       *spcowner = PQgetvalue(res, i, 1);
                char       *spclocation = PQgetvalue(res, i, 2);
                char       *spcacl = PQgetvalue(res, i, 3);
+               char       *spccomment = PQgetvalue(res, i, 4);
                char       *fspcname;
 
                /* needed for buildACLCommands() */
@@ -693,6 +721,12 @@ dumpTablespaces(PGconn *conn)
                        exit(1);
                }
 
+               if (spccomment && strlen(spccomment)) {
+                       appendPQExpBuffer(buf, "COMMENT ON TABLESPACE %s IS ", fspcname);
+                       appendStringLiteral(buf, spccomment, true);
+                       appendPQExpBuffer(buf, ";\n");
+               }
+
                printf("%s", buf->data);
 
                free(fspcname);
index a095e03..8bd2e14 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2000-2005, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.159 2006/02/12 02:54:30 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.160 2006/02/12 03:22:19 momjian Exp $
  */
 #include "postgres_fe.h"
 #include "command.h"
@@ -379,7 +379,7 @@ exec_command(const char *cmd,
                                break;
                        case 'g':
                                /* no longer distinct from \du */
-                               success = describeRoles(pattern);
+                               success = describeRoles(pattern, show_verbose);
                                break;
                        case 'l':
                                success = do_lo_list();
@@ -404,7 +404,7 @@ exec_command(const char *cmd,
                                success = listTables(&cmd[1], pattern, show_verbose);
                                break;
                        case 'u':
-                               success = describeRoles(pattern);
+                               success = describeRoles(pattern, show_verbose);
                                break;
 
                        default:
index 5caf16d..17ca722 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2000-2005, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.130 2005/11/22 18:17:29 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.131 2006/02/12 03:22:19 momjian Exp $
  */
 #include "postgres_fe.h"
 #include "describe.h"
@@ -127,8 +127,9 @@ describeTablespaces(const char *pattern, bool verbose)
 
        if (verbose)
                appendPQExpBuffer(&buf,
-                                                 ",\n  spcacl as \"%s\"",
-                                                 _("Access privileges"));
+                                                 ",\n  spcacl as \"%s\""
+                                                 ",\n  pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"",
+                                                 _("Access privileges"), _("Description"));
 
        appendPQExpBuffer(&buf,
                                          "\nFROM pg_catalog.pg_tablespace\n");
@@ -362,7 +363,7 @@ listAllDbs(bool verbose)
                                          _("Encoding"));
        if (verbose)
                appendPQExpBuffer(&buf,
-                                                 ",\n       pg_catalog.obj_description(d.oid, 'pg_database') as \"%s\"",
+                                                 ",\n       pg_catalog.shobj_description(d.oid, 'pg_database') as \"%s\"",
                                                  _("Description"));
        appendPQExpBuffer(&buf,
                                          "\nFROM pg_catalog.pg_database d"
@@ -1382,7 +1383,7 @@ add_tablespace_footer(char relkind, Oid tablespace, char **footers,
  * Describes roles.  Any schema portion of the pattern is ignored.
  */
 bool
-describeRoles(const char *pattern)
+describeRoles(const char *pattern, bool verbose)
 {
        PQExpBufferData buf;
        PGresult   *res;
@@ -1398,8 +1399,7 @@ describeRoles(const char *pattern)
                "  CASE WHEN r.rolconnlimit < 0 THEN CAST('%s' AS pg_catalog.text)\n"
                                          "       ELSE CAST(r.rolconnlimit AS pg_catalog.text)\n"
                                          "  END AS \"%s\", \n"
-                                         "  ARRAY(SELECT b.rolname FROM pg_catalog.pg_auth_members m JOIN pg_catalog.pg_roles b ON (m.roleid = b.oid) WHERE m.member = r.oid) as \"%s\"\n"
-                                         "FROM pg_catalog.pg_roles r\n",
+                                         "  ARRAY(SELECT b.rolname FROM pg_catalog.pg_auth_members m JOIN pg_catalog.pg_roles b ON (m.roleid = b.oid) WHERE m.member = r.oid) as \"%s\"",
                                          _("Role name"),
                                          _("yes"), _("no"), _("Superuser"),
                                          _("yes"), _("no"), _("Create role"),
@@ -1407,6 +1407,12 @@ describeRoles(const char *pattern)
                                          _("no limit"), _("Connections"),
                                          _("Member of"));
 
+       if (verbose)
+               appendPQExpBuffer(&buf, "\n, pg_catalog.shobj_description(r.oid, 'pg_authid') AS \"%s\"",
+                                               _("Description"));
+
+       appendPQExpBuffer(&buf, "\nFROM pg_catalog.pg_roles r\n");
+
        processNamePattern(&buf, pattern, false, false,
                                           NULL, "r.rolname", NULL, NULL);
 
index 22528f9..6289238 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2000-2005, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/psql/describe.h,v 1.29 2005/08/14 18:49:30 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/describe.h,v 1.30 2006/02/12 03:22:19 momjian Exp $
  */
 #ifndef DESCRIBE_H
 #define DESCRIBE_H
@@ -26,7 +26,7 @@ extern bool describeTypes(const char *pattern, bool verbose);
 extern bool describeOperators(const char *pattern);
 
 /* \du, \dg */
-extern bool describeRoles(const char *pattern);
+extern bool describeRoles(const char *pattern, bool verbose);
 
 /* \z (or \dp) */
 extern bool permissionsList(const char *pattern);
index fd32a52..f77b3a8 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2000-2005, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.145 2006/02/11 21:55:35 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.146 2006/02/12 03:22:19 momjian Exp $
  */
 
 /*----------------------------------------------------------------------
@@ -925,7 +925,8 @@ psql_completion(char *text, int start, int end)
                static const char *const list_COMMENT[] =
                {"CAST", "CONVERSION", "DATABASE", "INDEX", "LANGUAGE", "RULE", "SCHEMA",
                        "SEQUENCE", "TABLE", "TYPE", "VIEW", "COLUMN", "AGGREGATE", "FUNCTION",
-               "OPERATOR", "TRIGGER", "CONSTRAINT", "DOMAIN", "LARGE OBJECT", NULL};
+                       "OPERATOR", "TRIGGER", "CONSTRAINT", "DOMAIN", "LARGE OBJECT",
+                       "TABLESPACE", "ROLE", NULL};
 
                COMPLETE_WITH_LIST(list_COMMENT);
        }
index dd9dd24..1c2ac77 100644 (file)
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.314 2006/02/11 16:28:56 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.315 2006/02/12 03:22:19 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     200602111
+#define CATALOG_VERSION_NO     200602112
 
 #endif
index 6edbf23..e8c745f 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/indexing.h,v 1.92 2005/10/15 02:49:42 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/indexing.h,v 1.93 2006/02/12 03:22:19 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -139,6 +139,8 @@ DECLARE_INDEX(pg_depend_reference_index, 2674, on pg_depend using btree(refclass
 
 DECLARE_UNIQUE_INDEX(pg_description_o_c_o_index, 2675, on pg_description using btree(objoid oid_ops, classoid oid_ops, objsubid int4_ops));
 #define DescriptionObjIndexId  2675
+DECLARE_UNIQUE_INDEX(pg_shdescription_o_c_index, 2397, on pg_shdescription using btree(objoid oid_ops, classoid oid_ops));
+#define SharedDescriptionObjIndexId 2397
 
 /* This following index is not used for a cache and is not unique */
 DECLARE_INDEX(pg_index_indrelid_index, 2678, on pg_index using btree(indrelid oid_ops));
index ae81c65..a2ec3fd 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_database.h,v 1.38 2005/10/15 02:49:42 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_database.h,v 1.39 2006/02/12 03:22:19 momjian Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
@@ -75,7 +75,7 @@ typedef FormData_pg_database *Form_pg_database;
 #define Anum_pg_database_datacl                        12
 
 DATA(insert OID = 1 (  template1 PGUID ENCODING t t -1 0 0 0 1663 _null_ _null_ ));
-DESCR("Default template database");
+SHDESCR("Default template database");
 #define TemplateDbOid                  1
 
 #endif   /* PG_DATABASE_H */
index 93e186d..d8700b8 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.396 2006/02/11 20:39:58 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.397 2006/02/12 03:22:19 momjian Exp $
  *
  * NOTES
  *       The script catalog/genbki.sh reads this file and generates .bki
@@ -1513,6 +1513,8 @@ DATA(insert OID = 1215 (  obj_description PGNSP PGUID 14 f f t f s 2      25 "26 19"
 DESCR("get description for object id and catalog name");
 DATA(insert OID = 1216 (  col_description      PGNSP PGUID 14 f f t f s 2      25 "26 23" _null_ _null_ _null_ "select description from pg_catalog.pg_description where objoid = $1 and classoid = ''pg_catalog.pg_class''::regclass and objsubid = $2" - _null_ ));
 DESCR("get description for table column");
+DATA(insert OID = 1993 ( shobj_description     PGNSP PGUID 14 f f t f s 2      25 "26 19" _null_ _null_ _null_ "select description from pg_catalog.pg_shdescription where objoid = $1 and classoid = (select oid from pg_catalog.pg_class where relname = $2 and relnamespace = PGNSP)" - _null_ ));
+DESCR("get description for object id and shared catalog name");
 
 DATA(insert OID = 1217 (  date_trunc      PGNSP PGUID 12 f f t f s 2 1184 "25 1184" _null_ _null_ _null_ timestamptz_trunc - _null_ ));
 DESCR("truncate timestamp with time zone to specified units");
diff --git a/src/include/catalog/pg_shdescription.h b/src/include/catalog/pg_shdescription.h
new file mode 100644 (file)
index 0000000..6cc9c77
--- /dev/null
@@ -0,0 +1,80 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_shdescription.h
+ *       definition of the system "shared description" relation
+ *       (pg_shdescription)
+ *
+ * NOTE: an object is identified by the OID of the row that primarily
+ * defines the object, plus the OID of the table that that row appears in.
+ * For example, a database is identified by the OID of its pg_database row
+ * plus the pg_class OID of table pg_database.  This allows unique
+ * identification of objects without assuming that OIDs are unique
+ * across tables.
+ *
+ *
+ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * $PostgreSQL: pgsql/src/include/catalog/pg_shdescription.h,v 1.1 2006/02/12 03:22:21 momjian Exp $
+ *
+ * NOTES
+ *             the genbki.sh script reads this file and generates .bki
+ *             information from the DATA() statements.
+ *
+ *             XXX do NOT break up DATA() statements into multiple lines!
+ *                     the scripts are not as smart as you might think...
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_SHDESCRIPTION_H
+#define PG_SHDESCRIPTION_H
+
+/* ----------------
+ *             postgres.h contains the system type definitions and the
+ *             CATALOG(), BKI_BOOTSTRAP and DATA() sugar words so this file
+ *             can be read by both genbki.sh and the C compiler.
+ * ----------------
+ */
+
+/* ----------------
+ *             pg_shdescription definition.    cpp turns this into
+ *             typedef struct FormData_pg_shdescription
+ * ----------------
+ */
+#define SharedDescriptionRelationId  2396
+
+CATALOG(pg_shdescription,2396) BKI_SHARED_RELATION BKI_WITHOUT_OIDS
+{
+       Oid                     objoid;                 /* OID of object itself */
+       Oid                     classoid;               /* OID of table containing object */
+       text            description;    /* description of object */
+} FormData_pg_shdescription;
+
+/* ----------------
+ *             Form_pg_shdescription corresponds to a pointer to a tuple with
+ *             the format of pg_shdescription relation.
+ * ----------------
+ */
+typedef FormData_pg_shdescription *Form_pg_shdescription;
+
+/* ----------------
+ *             compiler constants for pg_shdescription
+ * ----------------
+ */
+#define Natts_pg_shdescription                 3       
+#define Anum_pg_shdescription_objoid           1
+#define Anum_pg_shdescription_classoid 2
+#define Anum_pg_shdescription_description 3
+
+/* ----------------
+ *             initial contents of pg_shdescription
+ * ----------------
+ */
+
+/*
+ *     Because the contents of this table are taken from the other *.h files,
+ *     there is no initialization here.  The initial contents are extracted
+ *     by genbki.sh and loaded during initdb.
+ */
+
+#endif   /* PG_SHDESCRIPTION_H */
index b27113e..7737e7e 100644 (file)
@@ -21,7 +21,8 @@
  * related routines.  CommentObject() implements the SQL "COMMENT ON"
  * command.  DeleteComments() deletes all comments for an object.
  * CreateComments creates (or deletes, if comment is NULL) a comment
- * for a specific key.
+ * for a specific key.  There are versions of these two methods for
+ * both normal and shared objects.
  *------------------------------------------------------------------
  */
 
@@ -31,4 +32,8 @@ extern void DeleteComments(Oid oid, Oid classoid, int32 subid);
 
 extern void CreateComments(Oid oid, Oid classoid, int32 subid, char *comment);
 
+extern void DeleteSharedComments(Oid oid, Oid classoid);
+
+extern void CreateSharedComments(Oid oid, Oid classoid, char *comment);
+
 #endif   /* COMMENT_H */
index 8d1a389..10d2ed4 100644 (file)
@@ -10,7 +10,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1995, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/postgres.h,v 1.72 2006/01/08 21:24:37 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/postgres.h,v 1.73 2006/02/12 03:22:19 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -539,6 +539,7 @@ extern int ExceptionalCondition(char *conditionName, char *errorType,
 /* these need to expand into some harmless, repeatable declaration */
 #define DATA(x)   extern int no_such_variable
 #define DESCR(x)  extern int no_such_variable
+#define SHDESCR(x) extern int no_such_variable
 
 typedef int4 aclitem;                  /* PHONY definition for catalog use only */
 
index 250de98..10edcb3 100644 (file)
@@ -59,6 +59,7 @@ SELECT relname, relhasindex
  pg_proc             | t
  pg_rewrite          | t
  pg_shdepend         | t
+ pg_shdescription    | t
  pg_statistic        | t
  pg_tablespace       | t
  pg_trigger          | t
@@ -68,7 +69,7 @@ SELECT relname, relhasindex
  shighway            | t
  tenk1               | t
  tenk2               | t
-(58 rows)
+(59 rows)
 
 --
 -- another sanity check: every system catalog that has OIDs should have