7
7
* Copyright (c) 1999-2001, PostgreSQL Global Development Group
8
8
*
9
9
* IDENTIFICATION
10
- * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.45 2002/04/27 03 :45:00 tgl Exp $
10
+ * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.46 2002/05/13 17 :45:30 tgl Exp $
11
11
*
12
12
*-------------------------------------------------------------------------
13
13
*/
50
50
static void CommentRelation (int objtype ,List * relname ,char * comment );
51
51
static void CommentAttribute (List * qualname ,char * comment );
52
52
static void CommentDatabase (List * qualname ,char * comment );
53
+ static void CommentNamespace (List * qualname ,char * comment );
53
54
static void CommentRule (List * qualname ,char * comment );
54
55
static void CommentType (List * typename ,char * comment );
55
56
static void CommentAggregate (List * aggregate ,List * arguments ,char * comment );
@@ -99,6 +100,9 @@ CommentObject(CommentStmt *stmt)
99
100
case TRIGGER :
100
101
CommentTrigger (stmt -> objname ,stmt -> comment );
101
102
break ;
103
+ case SCHEMA :
104
+ CommentNamespace (stmt -> objname ,stmt -> comment );
105
+ break ;
102
106
default :
103
107
elog (ERROR ,"An attempt was made to comment on a unknown type: %d" ,
104
108
stmt -> objtype );
@@ -332,22 +336,22 @@ CommentRelation(int objtype, List *relname, char *comment)
332
336
{
333
337
case INDEX :
334
338
if (relation -> rd_rel -> relkind != RELKIND_INDEX )
335
- elog (ERROR ,"relation'%s' is not an index" ,
339
+ elog (ERROR ,"relation\"%s\" is not an index" ,
336
340
RelationGetRelationName (relation ));
337
341
break ;
338
342
case TABLE :
339
343
if (relation -> rd_rel -> relkind != RELKIND_RELATION )
340
- elog (ERROR ,"relation'%s' is not a table" ,
344
+ elog (ERROR ,"relation\"%s\" is not a table" ,
341
345
RelationGetRelationName (relation ));
342
346
break ;
343
347
case VIEW :
344
348
if (relation -> rd_rel -> relkind != RELKIND_VIEW )
345
- elog (ERROR ,"relation'%s' is not a view" ,
349
+ elog (ERROR ,"relation\"%s\" is not a view" ,
346
350
RelationGetRelationName (relation ));
347
351
break ;
348
352
case SEQUENCE :
349
353
if (relation -> rd_rel -> relkind != RELKIND_SEQUENCE )
350
- elog (ERROR ,"relation'%s' is not a sequence" ,
354
+ elog (ERROR ,"relation\"%s\" is not a sequence" ,
351
355
RelationGetRelationName (relation ));
352
356
break ;
353
357
}
@@ -400,7 +404,7 @@ CommentAttribute(List *qualname, char *comment)
400
404
401
405
attnum = get_attnum (RelationGetRelid (relation ),attrname );
402
406
if (attnum == InvalidAttrNumber )
403
- elog (ERROR ,"'%s' is not an attribute of class'%s' " ,
407
+ elog (ERROR ,"\"%s\" is not an attribute of class\"%s\" " ,
404
408
attrname ,RelationGetRelationName (relation ));
405
409
406
410
/* Create the comment using the relation's oid */
@@ -451,13 +455,13 @@ CommentDatabase(List *qualname, char *comment)
451
455
/* Validate database exists, and fetch the db oid */
452
456
453
457
if (!HeapTupleIsValid (dbtuple ))
454
- elog (ERROR ,"database'%s' does not exist" ,database );
458
+ elog (ERROR ,"database\"%s\" does not exist" ,database );
455
459
oid = dbtuple -> t_data -> t_oid ;
456
460
457
461
/* Allow if the user matches the database dba or is a superuser */
458
462
459
463
if (!(superuser ()|| is_dbadmin (oid )))
460
- elog (ERROR ,"you are not permitted to comment on database'%s' " ,
464
+ elog (ERROR ,"you are not permitted to comment on database\"%s\" " ,
461
465
database );
462
466
463
467
/* Create the comments with the pg_database oid */
@@ -470,6 +474,51 @@ CommentDatabase(List *qualname, char *comment)
470
474
heap_close (pg_database ,AccessShareLock );
471
475
}
472
476
477
+ /*
478
+ * CommentNamespace --
479
+ *
480
+ * This routine is used to add/drop any user-comments a user might
481
+ * have regarding the specified namespace. The routine will check
482
+ * security for owner permissions, and, if succesful, will then
483
+ * attempt to find the oid of the namespace specified. Once found,
484
+ * a comment is added/dropped using the CreateComments() routine.
485
+ */
486
+ static void
487
+ CommentNamespace (List * qualname ,char * comment )
488
+ {
489
+ Oid oid ;
490
+ Oid classoid ;
491
+ HeapTuple tp ;
492
+ char * namespace ;
493
+
494
+ if (length (qualname )!= 1 )
495
+ elog (ERROR ,"CommentSchema: schema name may not be qualified" );
496
+ namespace = strVal (lfirst (qualname ));
497
+
498
+ tp = SearchSysCache (NAMESPACENAME ,
499
+ CStringGetDatum (namespace ),
500
+ 0 ,0 ,0 );
501
+ if (!HeapTupleIsValid (tp ))
502
+ elog (ERROR ,"CommentSchema: Schema \"%s\" could not be found" ,
503
+ namespace );
504
+
505
+ oid = tp -> t_data -> t_oid ;
506
+
507
+ /* Check object security */
508
+ if (!pg_namespace_ownercheck (oid ,GetUserId ()))
509
+ aclcheck_error (ACLCHECK_NOT_OWNER ,namespace );
510
+
511
+ /* pg_namespace doesn't have a hard-coded OID, so must look it up */
512
+ classoid = get_relname_relid (NamespaceRelationName ,PG_CATALOG_NAMESPACE );
513
+ Assert (OidIsValid (classoid ));
514
+
515
+ /* Call CreateComments() to create/drop the comments */
516
+ CreateComments (oid ,classoid ,0 ,comment );
517
+
518
+ /* Cleanup */
519
+ ReleaseSysCache (tp );
520
+ }
521
+
473
522
/*
474
523
* CommentRule --
475
524
*
@@ -528,12 +577,12 @@ CommentRule(List *qualname, char *comment)
528
577
}
529
578
else
530
579
{
531
- elog (ERROR ,"rule'%s' does not exist" ,rulename );
580
+ elog (ERROR ,"rule\"%s\" does not exist" ,rulename );
532
581
reloid = ruleoid = 0 ;/* keep compiler quiet */
533
582
}
534
583
535
584
if (HeapTupleIsValid (tuple = heap_getnext (scanDesc ,0 )))
536
- elog (ERROR ,"There are multiple rules'%s' "
585
+ elog (ERROR ,"There are multiple rules\"%s\" "
537
586
"\n\tPlease specify a relation name as well as a rule name" ,
538
587
rulename );
539
588
@@ -561,7 +610,7 @@ CommentRule(List *qualname, char *comment)
561
610
PointerGetDatum (rulename ),
562
611
0 ,0 );
563
612
if (!HeapTupleIsValid (tuple ))
564
- elog (ERROR ,"rule'%s' does not exist" ,rulename );
613
+ elog (ERROR ,"rule\"%s\" does not exist" ,rulename );
565
614
Assert (reloid == ((Form_pg_rewrite )GETSTRUCT (tuple ))-> ev_class );
566
615
ruleoid = tuple -> t_data -> t_oid ;
567
616
ReleaseSysCache (tuple );
@@ -574,7 +623,6 @@ CommentRule(List *qualname, char *comment)
574
623
aclcheck_error (aclcheck ,rulename );
575
624
576
625
/* pg_rewrite doesn't have a hard-coded OID, so must look it up */
577
-
578
626
classoid = get_relname_relid (RewriteRelationName ,PG_CATALOG_NAMESPACE );
579
627
Assert (OidIsValid (classoid ));
580
628
@@ -689,40 +737,30 @@ CommentProc(List *function, List *arguments, char *comment)
689
737
* its name and its argument list which defines the left and right
690
738
* hand types the operator will operate on. The argument list is
691
739
* expected to be a couple of parse nodes pointed to be a List
692
- * object. If the comments string is empty, the associated comment
693
- * is dropped.
694
- *
695
- * NOTE: we actually attach the comment to the procedure that underlies
696
- * the operator. This is a feature, not a bug: we want the same comment
697
- * to be visible for both operator and function.
740
+ * object.
698
741
*/
699
742
static void
700
743
CommentOperator (List * opername ,List * arguments ,char * comment )
701
744
{
702
745
TypeName * typenode1 = (TypeName * )lfirst (arguments );
703
746
TypeName * typenode2 = (TypeName * )lsecond (arguments );
704
747
Oid oid ;
748
+ Oid classoid ;
705
749
706
750
/* Look up the operator */
707
-
708
751
oid = LookupOperNameTypeNames (opername ,typenode1 ,typenode2 ,
709
752
"CommentOperator" );
710
753
711
754
/* Valid user's ability to comment on this operator */
712
-
713
755
if (!pg_oper_ownercheck (oid ,GetUserId ()))
714
756
aclcheck_error (ACLCHECK_NOT_OWNER ,NameListToString (opername ));
715
757
716
- /* Get the procedure associated with the operator */
717
-
718
- oid = get_opcode (oid );
719
- if (oid == InvalidOid )
720
- elog (ERROR ,"operator '%s' does not have an underlying function" ,
721
- NameListToString (opername ));
758
+ /* pg_operator doesn't have a hard-coded OID, so must look it up */
759
+ classoid = get_relname_relid (OperatorRelationName ,PG_CATALOG_NAMESPACE );
760
+ Assert (OidIsValid (classoid ));
722
761
723
762
/* Call CreateComments() to create/drop the comments */
724
-
725
- CreateComments (oid ,RelOid_pg_proc ,0 ,comment );
763
+ CreateComments (oid ,classoid ,0 ,comment );
726
764
}
727
765
728
766
/*
@@ -784,7 +822,7 @@ CommentTrigger(List *qualname, char *comment)
784
822
/* If no trigger exists for the relation specified, notify user */
785
823
786
824
if (!HeapTupleIsValid (triggertuple ))
787
- elog (ERROR ,"trigger'%s' for relation'%s' does not exist" ,
825
+ elog (ERROR ,"trigger\"%s\" for relation\"%s\" does not exist" ,
788
826
trigname ,RelationGetRelationName (relation ));
789
827
790
828
oid = triggertuple -> t_data -> t_oid ;