I've created a new shared catalog table pg_shdescription to store

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
This commit is contained in:
Bruce Momjian 2006-02-12 03:22:21 +00:00
parent 95dbf9c02f
commit f9a726aa88
25 changed files with 617 additions and 82 deletions

View 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">
@ -188,6 +188,11 @@
<entry>dependencies on shared objects</entry>
</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>
@ -2230,6 +2235,12 @@
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>
@ -3612,6 +3623,73 @@
</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>

View 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
-->
@ -9463,6 +9463,10 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
<primary>col_description</primary>
</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>
@ -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">

View 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>
@ -197,17 +200,15 @@ COMMENT ON
<refsect1>
<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';

View 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'

View 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

View 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"
@ -30,10 +31,13 @@
#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);
@ -240,6 +252,100 @@ CreateComments(Oid oid, Oid classoid, int32 subid, char *comment)
heap_close(description, NoLock);
}
/*
* 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
*
@ -292,6 +398,42 @@ DeleteComments(Oid oid, Oid classoid, int32 subid)
heap_close(description, RowExclusiveLock);
}
/*
* 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 --
*
@ -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)
{
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")));
return;
}
/* Check object security */
if (!pg_database_ownercheck(oid, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
database);
/* Call CreateComments() to create/drop the comments */
CreateComments(oid, DatabaseRelationId, 0, comment);
/* 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(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("tablespace \"%s\" does not exist", tablespace)));
return;
}
/* Check object security */
if (!pg_tablespace_ownercheck(oid, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TABLESPACE, tablespace);
/* 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);
}
/*

View 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.

View 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"
@ -428,6 +429,11 @@ DropTableSpace(DropTableSpaceStmt *stmt)
heap_endscan(scandesc);
/*
* Remove any comments on this tablespace.
*/
DeleteSharedComments(tablespaceoid, TableSpaceRelationId);
/*
* Remove dependency on owner.
*/

View 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"
@ -940,6 +941,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,

View 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:

View 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
};
@ -1751,6 +1754,42 @@ setup_description(void)
check_ok();
}
/*
* 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
*/
@ -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();

View 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);

View 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 "
"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, 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 "
"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, "
"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);

View 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:

View 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);

View 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);

View 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);
}

View 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

View 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));

View 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 */

View 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");

View File

@ -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 */

View 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 */

View 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 */

View 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