📄 comment.c
字号:
/* * Fetch the trigger tuple from pg_trigger. There can be only one because * of the unique index. */ pg_trigger = heap_open(TriggerRelationId, AccessShareLock); ScanKeyInit(&entry[0], Anum_pg_trigger_tgrelid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(RelationGetRelid(relation))); ScanKeyInit(&entry[1], Anum_pg_trigger_tgname, BTEqualStrategyNumber, F_NAMEEQ, CStringGetDatum(trigname)); scan = systable_beginscan(pg_trigger, TriggerRelidNameIndexId, true, SnapshotNow, 2, entry); triggertuple = systable_getnext(scan); /* If no trigger exists for the relation specified, notify user */ if (!HeapTupleIsValid(triggertuple)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("trigger \"%s\" for table \"%s\" does not exist", trigname, RelationGetRelationName(relation)))); oid = HeapTupleGetOid(triggertuple); systable_endscan(scan); /* Call CreateComments() to create/drop the comments */ CreateComments(oid, TriggerRelationId, 0, comment); /* Done, but hold lock on relation */ heap_close(pg_trigger, AccessShareLock); 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 voidCommentConstraint(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 = list_length(qualname); if (nnames < 2) /* parser messed up */ elog(ERROR, "must specify relation and constraint"); relName = list_truncate(list_copy(qualname), nnames - 1); conName = strVal(lfirst(list_tail(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, ACL_KIND_CLASS, 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_open(ConstraintRelationId, AccessShareLock); ScanKeyInit(&skey[0], Anum_pg_constraint_conrelid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(RelationGetRelid(relation))); scan = systable_beginscan(pg_constraint, ConstraintRelidIndexId, 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)) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("table \"%s\" has multiple constraints named \"%s\"", RelationGetRelationName(relation), conName))); conOid = HeapTupleGetOid(tuple); } } systable_endscan(scan); /* If no constraint exists for the relation specified, notify user */ if (!OidIsValid(conOid)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("constraint \"%s\" for table \"%s\" does not exist", conName, RelationGetRelationName(relation)))); /* Call CreateComments() to create/drop the comments */ CreateComments(conOid, ConstraintRelationId, 0, comment); /* Done, but hold lock on relation */ heap_close(pg_constraint, AccessShareLock); heap_close(relation, NoLock);}/* * CommentConversion -- * * This routine is used to add/drop any user-comments a user might * have regarding a CONVERSION. The conversion is specified by name * and, if found, and the user has appropriate permissions, a * comment will be added/dropped using the CreateComments() routine. * The conversion's name and the comment are the parameters to this routine. */static voidCommentConversion(List *qualname, char *comment){ Oid conversionOid; conversionOid = FindConversionByName(qualname); if (!OidIsValid(conversionOid)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("conversion \"%s\" does not exist", NameListToString(qualname)))); /* Check object security */ if (!pg_conversion_ownercheck(conversionOid, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CONVERSION, NameListToString(qualname)); /* Call CreateComments() to create/drop the comments */ CreateComments(conversionOid, ConversionRelationId, 0, comment);}/* * CommentLanguage -- * * This routine is used to add/drop any user-comments a user might * have regarding a LANGUAGE. The language is specified by name * and, if found, and the user has appropriate permissions, a * comment will be added/dropped using the CreateComments() routine. * The language's name and the comment are the parameters to this routine. */static voidCommentLanguage(List *qualname, char *comment){ Oid oid; char *language; if (list_length(qualname) != 1) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("language name may not be qualified"))); language = strVal(linitial(qualname)); oid = GetSysCacheOid(LANGNAME, CStringGetDatum(language), 0, 0, 0); if (!OidIsValid(oid)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_SCHEMA), errmsg("language \"%s\" does not exist", language))); /* Check object security */ if (!superuser()) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("must be superuser to comment on procedural language"))); /* Call CreateComments() to create/drop the comments */ CreateComments(oid, LanguageRelationId, 0, comment);}/* * CommentOpClass -- * * This routine is used to allow a user to provide comments on an * operator class. The operator class for commenting is determined by both * its name and its argument list which defines the index method * the operator class is used for. The argument list is expected to contain * a single name (represented as a string Value node). */static voidCommentOpClass(List *qualname, List *arguments, char *comment){ char *amname; char *schemaname; char *opcname; Oid amID; Oid opcID; HeapTuple tuple; Assert(list_length(arguments) == 1); amname = strVal(linitial(arguments)); /* * Get the access method's OID. */ amID = GetSysCacheOid(AMNAME, CStringGetDatum(amname), 0, 0, 0); if (!OidIsValid(amID)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("access method \"%s\" does not exist", amname))); /* * Look up the opclass. */ /* deconstruct the name list */ DeconstructQualifiedName(qualname, &schemaname, &opcname); if (schemaname) { /* Look in specific schema only */ Oid namespaceId; namespaceId = LookupExplicitNamespace(schemaname); tuple = SearchSysCache(CLAAMNAMENSP, ObjectIdGetDatum(amID), PointerGetDatum(opcname), ObjectIdGetDatum(namespaceId), 0); } else { /* Unqualified opclass name, so search the search path */ opcID = OpclassnameGetOpcid(amID, opcname); if (!OidIsValid(opcID)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("operator class \"%s\" does not exist for access method \"%s\"", opcname, amname))); tuple = SearchSysCache(CLAOID, ObjectIdGetDatum(opcID), 0, 0, 0); } if (!HeapTupleIsValid(tuple)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("operator class \"%s\" does not exist for access method \"%s\"", NameListToString(qualname), amname))); opcID = HeapTupleGetOid(tuple); /* Permission check: must own opclass */ if (!pg_opclass_ownercheck(opcID, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPCLASS, NameListToString(qualname)); ReleaseSysCache(tuple); /* Call CreateComments() to create/drop the comments */ CreateComments(opcID, OperatorClassRelationId, 0, comment);}/* * CommentLargeObject -- * * This routine is used to add/drop any user-comments a user might * have regarding a LARGE OBJECT. The large object is specified by OID * and, if found, and the user has appropriate permissions, a * comment will be added/dropped using the CreateComments() routine. * The large object's OID and the comment are the parameters to this routine. */static voidCommentLargeObject(List *qualname, char *comment){ Oid loid; Node *node; Assert(list_length(qualname) == 1); node = (Node *) linitial(qualname); switch (nodeTag(node)) { case T_Integer: loid = intVal(node); break; case T_Float: /* * Values too large for int4 will be represented as Float * constants by the lexer. Accept these if they are valid OID * strings. */ loid = DatumGetObjectId(DirectFunctionCall1(oidin, CStringGetDatum(strVal(node)))); break; default: elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node)); /* keep compiler quiet */ loid = InvalidOid; } /* check that the large object exists */ if (!LargeObjectExists(loid)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("large object %u does not exist", loid))); /* Call CreateComments() to create/drop the comments */ CreateComments(loid, LargeObjectRelationId, 0, comment);}/* * CommentCast -- * * This routine is used to add/drop any user-comments a user might * have regarding a CAST. The cast is specified by source and destination types * and, if found, and the user has appropriate permissions, a * comment will be added/dropped using the CreateComments() routine. * The cast's source type is passed as the "name", the destination type * as the "arguments". */static voidCommentCast(List *qualname, List *arguments, char *comment){ TypeName *sourcetype; TypeName *targettype; Oid sourcetypeid; Oid targettypeid; HeapTuple tuple; Oid castOid; Assert(list_length(qualname) == 1); sourcetype = (TypeName *) linitial(qualname); Assert(IsA(sourcetype, TypeName)); Assert(list_length(arguments) == 1); targettype = (TypeName *) linitial(arguments); Assert(IsA(targettype, TypeName)); sourcetypeid = typenameTypeId(sourcetype); if (!OidIsValid(sourcetypeid)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("source data type %s does not exist", TypeNameToString(sourcetype)))); targettypeid = typenameTypeId(targettype); if (!OidIsValid(targettypeid)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("target data type %s does not exist", TypeNameToString(targettype)))); tuple = SearchSysCache(CASTSOURCETARGET, ObjectIdGetDatum(sourcetypeid), ObjectIdGetDatum(targettypeid), 0, 0); if (!HeapTupleIsValid(tuple)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("cast from type %s to type %s does not exist", TypeNameToString(sourcetype), TypeNameToString(targettype)))); /* Get the OID of the cast */ castOid = HeapTupleGetOid(tuple); /* Permission check */ if (!pg_type_ownercheck(sourcetypeid, GetUserId()) && !pg_type_ownercheck(targettypeid, GetUserId())) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("must be owner of type %s or type %s", TypeNameToString(sourcetype), TypeNameToString(targettype)))); ReleaseSysCache(tuple); /* Call CreateComments() to create/drop the comments */ CreateComments(castOid, CastRelationId, 0, comment);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -