Commit d5fa19c6 authored by Tom Lane's avatar Tom Lane

Add COMMENT ON CONSTRAINT facility (from Rod Taylor's pg_constraint patch).

Fix comment.c to not depend on parser token values, per discussion awhile
back.
parent c4fb2b4e
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Copyright (c) 1996-2001, PostgreSQL Global Development Group * Copyright (c) 1996-2001, PostgreSQL Global Development Group
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.50 2002/07/12 18:43:15 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.51 2002/07/14 23:38:13 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "catalog/catname.h" #include "catalog/catname.h"
#include "catalog/indexing.h" #include "catalog/indexing.h"
#include "catalog/namespace.h" #include "catalog/namespace.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_database.h" #include "catalog/pg_database.h"
#include "catalog/pg_description.h" #include "catalog/pg_description.h"
#include "catalog/pg_namespace.h" #include "catalog/pg_namespace.h"
...@@ -30,7 +31,6 @@ ...@@ -30,7 +31,6 @@
#include "parser/parse_func.h" #include "parser/parse_func.h"
#include "parser/parse_oper.h" #include "parser/parse_oper.h"
#include "parser/parse_type.h" #include "parser/parse_type.h"
#include "parser/parse.h"
#include "utils/acl.h" #include "utils/acl.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/fmgroids.h" #include "utils/fmgroids.h"
...@@ -57,6 +57,7 @@ static void CommentAggregate(List *aggregate, List *arguments, char *comment); ...@@ -57,6 +57,7 @@ static void CommentAggregate(List *aggregate, List *arguments, char *comment);
static void CommentProc(List *function, List *arguments, char *comment); static void CommentProc(List *function, List *arguments, char *comment);
static void CommentOperator(List *opername, List *arguments, char *comment); static void CommentOperator(List *opername, List *arguments, char *comment);
static void CommentTrigger(List *qualname, char *comment); static void CommentTrigger(List *qualname, char *comment);
static void CommentConstraint(List *qualname, char *comment);
/* /*
...@@ -70,39 +71,42 @@ CommentObject(CommentStmt *stmt) ...@@ -70,39 +71,42 @@ CommentObject(CommentStmt *stmt)
{ {
switch (stmt->objtype) switch (stmt->objtype)
{ {
case INDEX: case COMMENT_ON_INDEX:
case SEQUENCE: case COMMENT_ON_SEQUENCE:
case TABLE: case COMMENT_ON_TABLE:
case VIEW: case COMMENT_ON_VIEW:
CommentRelation(stmt->objtype, stmt->objname, stmt->comment); CommentRelation(stmt->objtype, stmt->objname, stmt->comment);
break; break;
case COLUMN: case COMMENT_ON_COLUMN:
CommentAttribute(stmt->objname, stmt->comment); CommentAttribute(stmt->objname, stmt->comment);
break; break;
case DATABASE: case COMMENT_ON_DATABASE:
CommentDatabase(stmt->objname, stmt->comment); CommentDatabase(stmt->objname, stmt->comment);
break; break;
case RULE: case COMMENT_ON_RULE:
CommentRule(stmt->objname, stmt->comment); CommentRule(stmt->objname, stmt->comment);
break; break;
case TYPE_P: case COMMENT_ON_TYPE:
CommentType(stmt->objname, stmt->comment); CommentType(stmt->objname, stmt->comment);
break; break;
case AGGREGATE: case COMMENT_ON_AGGREGATE:
CommentAggregate(stmt->objname, stmt->objargs, stmt->comment); CommentAggregate(stmt->objname, stmt->objargs, stmt->comment);
break; break;
case FUNCTION: case COMMENT_ON_FUNCTION:
CommentProc(stmt->objname, stmt->objargs, stmt->comment); CommentProc(stmt->objname, stmt->objargs, stmt->comment);
break; break;
case OPERATOR: case COMMENT_ON_OPERATOR:
CommentOperator(stmt->objname, stmt->objargs, stmt->comment); CommentOperator(stmt->objname, stmt->objargs, stmt->comment);
break; break;
case TRIGGER: case COMMENT_ON_TRIGGER:
CommentTrigger(stmt->objname, stmt->comment); CommentTrigger(stmt->objname, stmt->comment);
break; break;
case SCHEMA: case COMMENT_ON_SCHEMA:
CommentNamespace(stmt->objname, stmt->comment); CommentNamespace(stmt->objname, stmt->comment);
break; break;
case COMMENT_ON_CONSTRAINT:
CommentConstraint(stmt->objname, stmt->comment);
break;
default: default:
elog(ERROR, "An attempt was made to comment on a unknown type: %d", elog(ERROR, "An attempt was made to comment on a unknown type: %d",
stmt->objtype); stmt->objtype);
...@@ -309,26 +313,26 @@ CommentRelation(int objtype, List *relname, char *comment) ...@@ -309,26 +313,26 @@ CommentRelation(int objtype, List *relname, char *comment)
switch (objtype) switch (objtype)
{ {
case INDEX: case COMMENT_ON_INDEX:
if (relation->rd_rel->relkind != RELKIND_INDEX) if (relation->rd_rel->relkind != RELKIND_INDEX)
elog(ERROR, "relation \"%s\" is not an index", elog(ERROR, "relation \"%s\" is not an index",
RelationGetRelationName(relation)); RelationGetRelationName(relation));
break; break;
case TABLE: case COMMENT_ON_SEQUENCE:
if (relation->rd_rel->relkind != RELKIND_SEQUENCE)
elog(ERROR, "relation \"%s\" is not a sequence",
RelationGetRelationName(relation));
break;
case COMMENT_ON_TABLE:
if (relation->rd_rel->relkind != RELKIND_RELATION) if (relation->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "relation \"%s\" is not a table", elog(ERROR, "relation \"%s\" is not a table",
RelationGetRelationName(relation)); RelationGetRelationName(relation));
break; break;
case VIEW: case COMMENT_ON_VIEW:
if (relation->rd_rel->relkind != RELKIND_VIEW) if (relation->rd_rel->relkind != RELKIND_VIEW)
elog(ERROR, "relation \"%s\" is not a view", elog(ERROR, "relation \"%s\" is not a view",
RelationGetRelationName(relation)); RelationGetRelationName(relation));
break; break;
case SEQUENCE:
if (relation->rd_rel->relkind != RELKIND_SEQUENCE)
elog(ERROR, "relation \"%s\" is not a sequence",
RelationGetRelationName(relation));
break;
} }
/* Create the comment using the relation's oid */ /* Create the comment using the relation's oid */
...@@ -439,7 +443,7 @@ CommentDatabase(List *qualname, char *comment) ...@@ -439,7 +443,7 @@ CommentDatabase(List *qualname, char *comment)
elog(ERROR, "you are not permitted to comment on database \"%s\"", elog(ERROR, "you are not permitted to comment on database \"%s\"",
database); database);
/* Create the comments with the pg_database oid */ /* Create the comment with the pg_database oid */
CreateComments(oid, RelOid_pg_database, 0, comment); CreateComments(oid, RelOid_pg_database, 0, comment);
...@@ -805,7 +809,7 @@ CommentTrigger(List *qualname, char *comment) ...@@ -805,7 +809,7 @@ CommentTrigger(List *qualname, char *comment)
systable_endscan(scan); systable_endscan(scan);
/* Create the comments with the pg_trigger oid */ /* Create the comment with the pg_trigger oid */
CreateComments(oid, RelationGetRelid(pg_trigger), 0, comment); CreateComments(oid, RelationGetRelid(pg_trigger), 0, comment);
...@@ -814,3 +818,83 @@ CommentTrigger(List *qualname, char *comment) ...@@ -814,3 +818,83 @@ CommentTrigger(List *qualname, char *comment)
heap_close(pg_trigger, AccessShareLock); heap_close(pg_trigger, AccessShareLock);
heap_close(relation, NoLock); heap_close(relation, NoLock);
} }
/*
* CommentConstraint --
*
* Enable commenting on constraints held within the pg_constraint
* table. A qualified name is required as constraint names are
* unique per relation.
*/
static void
CommentConstraint(List *qualname, char *comment)
{
int nnames;
List *relName;
char *conName;
RangeVar *rel;
Relation pg_constraint,
relation;
HeapTuple tuple;
SysScanDesc scan;
ScanKeyData skey[1];
Oid conOid = InvalidOid;
/* Separate relname and constraint name */
nnames = length(qualname);
if (nnames < 2)
elog(ERROR, "CommentConstraint: must specify relation and constraint");
relName = ltruncate(nnames-1, listCopy(qualname));
conName = strVal(nth(nnames-1, qualname));
/* Open the owning relation to ensure it won't go away meanwhile */
rel = makeRangeVarFromNameList(relName);
relation = heap_openrv(rel, AccessShareLock);
/* Check object security */
if (!pg_class_ownercheck(RelationGetRelid(relation), GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(relation));
/*
* Fetch the constraint tuple from pg_constraint. There may be more than
* one match, because constraints are not required to have unique names;
* if so, error out.
*/
pg_constraint = heap_openr(ConstraintRelationName, AccessShareLock);
ScanKeyEntryInitialize(&skey[0], 0x0,
Anum_pg_constraint_conrelid, F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(relation)));
scan = systable_beginscan(pg_constraint, ConstraintRelidIndex, true,
SnapshotNow, 1, skey);
while (HeapTupleIsValid(tuple = systable_getnext(scan)))
{
Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tuple);
if (strcmp(NameStr(con->conname), conName) == 0)
{
if (OidIsValid(conOid))
elog(ERROR, "Relation \"%s\" has multiple constraints named \"%s\"",
RelationGetRelationName(relation), conName);
conOid = tuple->t_data->t_oid;
}
}
systable_endscan(scan);
/* If no constraint exists for the relation specified, notify user */
if (!OidIsValid(conOid))
elog(ERROR, "constraint \"%s\" for relation \"%s\" does not exist",
conName, RelationGetRelationName(relation));
/* Create the comment with the pg_constraint oid */
CreateComments(conOid, RelationGetRelid(pg_constraint), 0, comment);
/* Done, but hold lock on relation */
heap_close(pg_constraint, AccessShareLock);
heap_close(relation, NoLock);
}
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.339 2002/07/12 18:43:17 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.340 2002/07/14 23:38:13 tgl Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -2364,7 +2364,7 @@ CommentStmt: ...@@ -2364,7 +2364,7 @@ CommentStmt:
IS comment_text IS comment_text
{ {
CommentStmt *n = makeNode(CommentStmt); CommentStmt *n = makeNode(CommentStmt);
n->objtype = AGGREGATE; n->objtype = COMMENT_ON_AGGREGATE;
n->objname = $4; n->objname = $4;
n->objargs = makeList1($6); n->objargs = makeList1($6);
n->comment = $9; n->comment = $9;
...@@ -2373,7 +2373,7 @@ CommentStmt: ...@@ -2373,7 +2373,7 @@ CommentStmt:
| COMMENT ON FUNCTION func_name func_args IS comment_text | COMMENT ON FUNCTION func_name func_args IS comment_text
{ {
CommentStmt *n = makeNode(CommentStmt); CommentStmt *n = makeNode(CommentStmt);
n->objtype = FUNCTION; n->objtype = COMMENT_ON_FUNCTION;
n->objname = $4; n->objname = $4;
n->objargs = $5; n->objargs = $5;
n->comment = $7; n->comment = $7;
...@@ -2383,16 +2383,16 @@ CommentStmt: ...@@ -2383,16 +2383,16 @@ CommentStmt:
IS comment_text IS comment_text
{ {
CommentStmt *n = makeNode(CommentStmt); CommentStmt *n = makeNode(CommentStmt);
n->objtype = OPERATOR; n->objtype = COMMENT_ON_OPERATOR;
n->objname = $4; n->objname = $4;
n->objargs = $6; n->objargs = $6;
n->comment = $9; n->comment = $9;
$$ = (Node *) n; $$ = (Node *) n;
} }
| COMMENT ON TRIGGER name ON any_name IS comment_text | COMMENT ON CONSTRAINT name ON any_name IS comment_text
{ {
CommentStmt *n = makeNode(CommentStmt); CommentStmt *n = makeNode(CommentStmt);
n->objtype = TRIGGER; n->objtype = COMMENT_ON_CONSTRAINT;
n->objname = lappend($6, makeString($4)); n->objname = lappend($6, makeString($4));
n->objargs = NIL; n->objargs = NIL;
n->comment = $8; n->comment = $8;
...@@ -2401,7 +2401,7 @@ CommentStmt: ...@@ -2401,7 +2401,7 @@ CommentStmt:
| COMMENT ON RULE name ON any_name IS comment_text | COMMENT ON RULE name ON any_name IS comment_text
{ {
CommentStmt *n = makeNode(CommentStmt); CommentStmt *n = makeNode(CommentStmt);
n->objtype = RULE; n->objtype = COMMENT_ON_RULE;
n->objname = lappend($6, makeString($4)); n->objname = lappend($6, makeString($4));
n->objargs = NIL; n->objargs = NIL;
n->comment = $8; n->comment = $8;
...@@ -2411,29 +2411,38 @@ CommentStmt: ...@@ -2411,29 +2411,38 @@ CommentStmt:
{ {
/* Obsolete syntax supported for awhile for compatibility */ /* Obsolete syntax supported for awhile for compatibility */
CommentStmt *n = makeNode(CommentStmt); CommentStmt *n = makeNode(CommentStmt);
n->objtype = RULE; n->objtype = COMMENT_ON_RULE;
n->objname = makeList1(makeString($4)); n->objname = makeList1(makeString($4));
n->objargs = NIL; n->objargs = NIL;
n->comment = $6; n->comment = $6;
$$ = (Node *) n; $$ = (Node *) n;
} }
| COMMENT ON TRIGGER name ON any_name IS comment_text
{
CommentStmt *n = makeNode(CommentStmt);
n->objtype = COMMENT_ON_TRIGGER;
n->objname = lappend($6, makeString($4));
n->objargs = NIL;
n->comment = $8;
$$ = (Node *) n;
}
; ;
comment_type: comment_type:
COLUMN { $$ = COLUMN; } COLUMN { $$ = COMMENT_ON_COLUMN; }
| DATABASE { $$ = DATABASE; } | DATABASE { $$ = COMMENT_ON_DATABASE; }
| SCHEMA { $$ = SCHEMA; } | SCHEMA { $$ = COMMENT_ON_SCHEMA; }
| INDEX { $$ = INDEX; } | INDEX { $$ = COMMENT_ON_INDEX; }
| SEQUENCE { $$ = SEQUENCE; } | SEQUENCE { $$ = COMMENT_ON_SEQUENCE; }
| TABLE { $$ = TABLE; } | TABLE { $$ = COMMENT_ON_TABLE; }
| DOMAIN_P { $$ = TYPE_P; } | DOMAIN_P { $$ = COMMENT_ON_TYPE; }
| TYPE_P { $$ = TYPE_P; } | TYPE_P { $$ = COMMENT_ON_TYPE; }
| VIEW { $$ = VIEW; } | VIEW { $$ = COMMENT_ON_VIEW; }
; ;
comment_text: comment_text:
Sconst { $$ = $1; } Sconst { $$ = $1; }
| NULL_P { $$ = NULL; } | NULL_P { $$ = NULL; }
; ;
/***************************************************************************** /*****************************************************************************
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: parsenodes.h,v 1.185 2002/07/12 18:43:19 tgl Exp $ * $Id: parsenodes.h,v 1.186 2002/07/14 23:38:13 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1165,10 +1165,25 @@ typedef struct TruncateStmt ...@@ -1165,10 +1165,25 @@ typedef struct TruncateStmt
* Comment On Statement * Comment On Statement
* ---------------------- * ----------------------
*/ */
#define COMMENT_ON_AGGREGATE 100
#define COMMENT_ON_COLUMN 101
#define COMMENT_ON_CONSTRAINT 102
#define COMMENT_ON_DATABASE 103
#define COMMENT_ON_FUNCTION 104
#define COMMENT_ON_INDEX 105
#define COMMENT_ON_OPERATOR 106
#define COMMENT_ON_RULE 107
#define COMMENT_ON_SCHEMA 108
#define COMMENT_ON_SEQUENCE 109
#define COMMENT_ON_TABLE 110
#define COMMENT_ON_TRIGGER 111
#define COMMENT_ON_TYPE 112
#define COMMENT_ON_VIEW 113
typedef struct CommentStmt typedef struct CommentStmt
{ {
NodeTag type; NodeTag type;
int objtype; /* Object's type */ int objtype; /* Object's type, see codes above */
List *objname; /* Qualified name of the object */ List *objname; /* Qualified name of the object */
List *objargs; /* Arguments if needed (eg, for functions) */ List *objargs; /* Arguments if needed (eg, for functions) */
char *comment; /* Comment to insert, or NULL to remove */ char *comment; /* Comment to insert, or NULL to remove */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment