Index: src/backend/commands/comment.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/commands/comment.c,v
retrieving revision 1.45
diff -c -r1.45 comment.c
*** src/backend/commands/comment.c	2002/04/27 03:45:00	1.45
--- src/backend/commands/comment.c	2002/05/13 01:55:01
***************
*** 50,55 ****
--- 50,56 ----
  static void CommentRelation(int objtype, List *relname, char *comment);
  static void CommentAttribute(List *qualname, char *comment);
  static void CommentDatabase(List *qualname, char *comment);
+ static void CommentNamespace(List *qualname, char *comment);
  static void CommentRule(List *qualname, char *comment);
  static void CommentType(List *typename, char *comment);
  static void CommentAggregate(List *aggregate, List *arguments, char *comment);
***************
*** 99,104 ****
--- 100,108 ----
  		case TRIGGER:
  			CommentTrigger(stmt->objname, stmt->comment);
  			break;
+ 		case SCHEMA:
+ 			CommentNamespace(stmt->objname, stmt->comment);
+ 			break;
  		default:
  			elog(ERROR, "An attempt was made to comment on a unknown type: %d",
  				 stmt->objtype);
***************
*** 471,476 ****
--- 475,527 ----
  }
  
  /*
+  * CommentNamespace --
+  *
+  * This routine is used to add/drop any user-comments a user might
+  * have regarding the specified namespace. The routine will check
+  * security for owner permissions, and, if succesful, will then
+  * attempt to find the oid of the namespace specified. Once found,
+  * a comment is added/dropped using the CreateComments() routine.
+  */
+ static void
+ CommentNamespace(List *qualname, char *comment)
+ {
+ 	Oid			oid;
+ 	Oid			nameOid;
+ 	HeapTuple	tp;
+ 	char	   *namespace;
+ 
+ 	if (length(qualname) != 1)
+ 		elog(ERROR, "CommentSchema: schema name may not be qualified");
+ 	namespace = strVal(lfirst(qualname));
+ 
+ 	tp = SearchSysCache(NAMESPACENAME,
+ 						CStringGetDatum(namespace),
+ 						0, 0, 0);
+ 	if (!HeapTupleIsValid(tp))
+ 		elog(ERROR, "CommentSchema: Schema '%s' could not be found",
+ 			 namespace);
+ 
+ 	oid = tp->t_data->t_oid;
+ 
+ 	/* Check object security */
+ 	if (!pg_namespace_ownercheck(oid, GetUserId()))
+ 		aclcheck_error(ACLCHECK_NOT_OWNER, namespace);
+ 
+ 	/* Get Namespace relation Oid */
+ 	nameOid = GetSysCacheOid(RELNAMENSP,
+ 							 CStringGetDatum(NamespaceRelationName),
+ 							 ObjectIdGetDatum(PG_CATALOG_NAMESPACE),
+ 							 0, 0);
+ 
+ 	/* Call CreateComments() to create/drop the comments */
+ 	CreateComments(oid, nameOid, 0, comment);
+ 
+ 	/* Cleanup */
+ 	ReleaseSysCache(tp);
+ }
+ 
+ /*
   * CommentRule --
   *
   * This routine is used to add/drop any user-comments a user might
***************
*** 689,700 ****
   * its name and its argument list which defines the left and right
   * hand types the operator will operate on. The argument list is
   * expected to be a couple of parse nodes pointed to be a List
!  * object. If the comments string is empty, the associated comment
!  * is dropped.
!  *
!  * NOTE: we actually attach the comment to the procedure that underlies
!  * the operator.  This is a feature, not a bug: we want the same comment
!  * to be visible for both operator and function.
   */
  static void
  CommentOperator(List *opername, List *arguments, char *comment)
--- 740,746 ----
   * its name and its argument list which defines the left and right
   * hand types the operator will operate on. The argument list is
   * expected to be a couple of parse nodes pointed to be a List
!  * object.
   */
  static void
  CommentOperator(List *opername, List *arguments, char *comment)
***************
*** 702,728 ****
  	TypeName   *typenode1 = (TypeName *) lfirst(arguments);
  	TypeName   *typenode2 = (TypeName *) lsecond(arguments);
  	Oid			oid;
  
  	/* Look up the operator */
- 
  	oid = LookupOperNameTypeNames(opername, typenode1, typenode2,
  								  "CommentOperator");
  
  	/* Valid user's ability to comment on this operator */
- 
  	if (!pg_oper_ownercheck(oid, GetUserId()))
  		aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(opername));
  
! 	/* Get the procedure associated with the operator */
  
- 	oid = get_opcode(oid);
- 	if (oid == InvalidOid)
- 		elog(ERROR, "operator '%s' does not have an underlying function",
- 			 NameListToString(opername));
- 
  	/* Call CreateComments() to create/drop the comments */
! 
! 	CreateComments(oid, RelOid_pg_proc, 0, comment);
  }
  
  /*
--- 748,770 ----
  	TypeName   *typenode1 = (TypeName *) lfirst(arguments);
  	TypeName   *typenode2 = (TypeName *) lsecond(arguments);
  	Oid			oid;
+ 	Oid			opOid;
  
  	/* Look up the operator */
  	oid = LookupOperNameTypeNames(opername, typenode1, typenode2,
  								  "CommentOperator");
  
  	/* Valid user's ability to comment on this operator */
  	if (!pg_oper_ownercheck(oid, GetUserId()))
  		aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(opername));
  
! 	opOid = GetSysCacheOid(RELNAMENSP,
! 						   CStringGetDatum(OperatorRelationName),
! 						   ObjectIdGetDatum(PG_CATALOG_NAMESPACE),
! 						   0, 0);
  
  	/* Call CreateComments() to create/drop the comments */
! 	CreateComments(oid, opOid, 0, comment);
  }
  
  /*
Index: src/backend/parser/gram.y
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/parser/gram.y,v
retrieving revision 2.314
diff -c -r2.314 gram.y
*** src/backend/parser/gram.y	2002/05/12 20:10:04	2.314
--- src/backend/parser/gram.y	2002/05/13 01:55:10
***************
*** 2278,2283 ****
--- 2278,2284 ----
  
  comment_type:	COLUMN { $$ = COLUMN; }
  		| DATABASE { $$ = DATABASE; }
+ 		| SCHEMA { $$ = SCHEMA; }
  		| INDEX { $$ = INDEX; }
  		| SEQUENCE { $$ = SEQUENCE; }
  		| TABLE { $$ = TABLE; }
Index: src/bin/psql/describe.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/describe.c,v
retrieving revision 1.53
diff -c -r1.53 describe.c
*** src/bin/psql/describe.c	2002/04/25 02:56:56	1.53
--- src/bin/psql/describe.c	2002/05/13 01:55:15
***************
*** 210,216 ****
  			 "  CASE WHEN o.oprkind='l' THEN NULL ELSE format_type(o.oprleft, NULL) END AS \"%s\",\n"
  			 "  CASE WHEN o.oprkind='r' THEN NULL ELSE format_type(o.oprright, NULL) END AS \"%s\",\n"
  			 "  format_type(o.oprresult, NULL) AS \"%s\",\n"
! 			 "  obj_description(o.oprcode, 'pg_proc') AS \"%s\"\n"
  			 "FROM pg_operator o\n",
  			 _("Name"), _("Left arg type"), _("Right arg type"),
  			 _("Result type"), _("Description"));
--- 210,217 ----
  			 "  CASE WHEN o.oprkind='l' THEN NULL ELSE format_type(o.oprleft, NULL) END AS \"%s\",\n"
  			 "  CASE WHEN o.oprkind='r' THEN NULL ELSE format_type(o.oprright, NULL) END AS \"%s\",\n"
  			 "  format_type(o.oprresult, NULL) AS \"%s\",\n"
! 			 "  coalesce(obj_description(o.oid, 'pg_operator'),"
! 			 "           obj_description(o.oprcode, 'pg_proc')) AS \"%s\"\n"
  			 "FROM pg_operator o\n",
  			 _("Name"), _("Left arg type"), _("Right arg type"),
  			 _("Result type"), _("Description"));
