comment.c
来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 916 行 · 第 1/2 页
C
916 行
CreateComments(oid, RelOid_pg_database, 0, comment);}/* * 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 successful, will then * attempt to find the oid of the namespace specified. Once found, * a comment is added/dropped using the CreateComments() routine. */static voidCommentNamespace(List *qualname, char *comment){ Oid oid; Oid classoid; char *namespace; if (length(qualname) != 1) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("schema name may not be qualified"))); namespace = strVal(lfirst(qualname)); oid = GetSysCacheOid(NAMESPACENAME, CStringGetDatum(namespace), 0, 0, 0); if (!OidIsValid(oid)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_SCHEMA), errmsg("schema \"%s\" does not exist", namespace))); /* Check object security */ if (!pg_namespace_ownercheck(oid, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_NAMESPACE, namespace); /* pg_namespace doesn't have a hard-coded OID, so must look it up */ classoid = get_system_catalog_relid(NamespaceRelationName); /* Call CreateComments() to create/drop the comments */ CreateComments(oid, classoid, 0, comment);}/* * CommentRule -- * * This routine is used to add/drop any user-comments a user might * have regarding a specified RULE. The rule for commenting is determined by * both its name and the relation to which it refers. The arguments to this * function are the rule name and relation name (merged into a qualified * name), and the comment to add/drop. * * Before PG 7.3, rules had unique names across the whole database, and so * the syntax was just COMMENT ON RULE rulename, with no relation name. * For purposes of backwards compatibility, we support that as long as there * is only one rule by the specified name in the database. */static voidCommentRule(List *qualname, char *comment){ int nnames; List *relname; char *rulename; RangeVar *rel; Relation relation; HeapTuple tuple; Oid reloid; Oid ruleoid; Oid classoid; AclResult aclcheck; /* Separate relname and trig name */ nnames = length(qualname); if (nnames == 1) { /* Old-style: only a rule name is given */ Relation RewriteRelation; HeapScanDesc scanDesc; ScanKeyData scanKeyData; rulename = strVal(lfirst(qualname)); /* Search pg_rewrite for such a rule */ ScanKeyEntryInitialize(&scanKeyData, 0, Anum_pg_rewrite_rulename, F_NAMEEQ, PointerGetDatum(rulename)); RewriteRelation = heap_openr(RewriteRelationName, AccessShareLock); scanDesc = heap_beginscan(RewriteRelation, SnapshotNow, 1, &scanKeyData); tuple = heap_getnext(scanDesc, ForwardScanDirection); if (HeapTupleIsValid(tuple)) { reloid = ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class; ruleoid = HeapTupleGetOid(tuple); } else { ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("rule \"%s\" does not exist", rulename))); reloid = ruleoid = 0; /* keep compiler quiet */ } if (HeapTupleIsValid(tuple = heap_getnext(scanDesc, ForwardScanDirection))) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("there are multiple rules named \"%s\"", rulename), errhint("Specify a relation name as well as a rule name."))); heap_endscan(scanDesc); heap_close(RewriteRelation, AccessShareLock); /* Open the owning relation to ensure it won't go away meanwhile */ relation = heap_open(reloid, AccessShareLock); } else { /* New-style: rule and relname both provided */ Assert(nnames >= 2); relname = ltruncate(nnames - 1, listCopy(qualname)); rulename = strVal(llast(qualname)); /* Open the owning relation to ensure it won't go away meanwhile */ rel = makeRangeVarFromNameList(relname); relation = heap_openrv(rel, AccessShareLock); reloid = RelationGetRelid(relation); /* Find the rule's pg_rewrite tuple, get its OID */ tuple = SearchSysCache(RULERELNAME, ObjectIdGetDatum(reloid), PointerGetDatum(rulename), 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "cache lookup failed for rule \"%s\"", rulename); Assert(reloid == ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class); ruleoid = HeapTupleGetOid(tuple); ReleaseSysCache(tuple); } /* Check object security */ aclcheck = pg_class_aclcheck(reloid, GetUserId(), ACL_RULE); if (aclcheck != ACLCHECK_OK) aclcheck_error(aclcheck, ACL_KIND_CLASS, get_rel_name(reloid)); /* pg_rewrite doesn't have a hard-coded OID, so must look it up */ classoid = get_system_catalog_relid(RewriteRelationName); /* Call CreateComments() to create/drop the comments */ CreateComments(ruleoid, classoid, 0, comment); heap_close(relation, NoLock);}/* * CommentType -- * * This routine is used to add/drop any user-comments a user might * have regarding a TYPE. The type is specified by name * and, if found, and the user has appropriate permissions, a * comment will be added/dropped using the CreateComments() routine. * The type's name and the comments are the parameters to this routine. */static voidCommentType(List *typename, char *comment){ TypeName *tname; Oid oid; /* XXX a bit of a crock; should accept TypeName in COMMENT syntax */ tname = makeNode(TypeName); tname->names = typename; tname->typmod = -1; /* Find the type's oid */ oid = typenameTypeId(tname); /* Check object security */ if (!pg_type_ownercheck(oid, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE, TypeNameToString(tname)); /* Call CreateComments() to create/drop the comments */ CreateComments(oid, RelOid_pg_type, 0, comment);}/* * CommentAggregate -- * * This routine is used to allow a user to provide comments on an * aggregate function. The aggregate function is determined by both * its name and its argument type, which, with the comments are * the three parameters handed to this routine. */static voidCommentAggregate(List *aggregate, List *arguments, char *comment){ TypeName *aggtype = (TypeName *) lfirst(arguments); Oid baseoid, oid; /* First, attempt to determine the base aggregate oid */ if (aggtype) baseoid = typenameTypeId(aggtype); else baseoid = ANYOID; /* Now, attempt to find the actual tuple in pg_proc */ oid = find_aggregate_func(aggregate, baseoid, false); /* Next, validate the user's attempt to comment */ if (!pg_proc_ownercheck(oid, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC, NameListToString(aggregate)); /* Call CreateComments() to create/drop the comments */ CreateComments(oid, RelOid_pg_proc, 0, comment);}/* * CommentProc -- * * This routine is used to allow a user to provide comments on an * procedure (function). The procedure is determined by both * its name and its argument list. The argument list is expected to * be a series of parsed nodes pointed to by a List object. If the * comments string is empty, the associated comment is dropped. */static voidCommentProc(List *function, List *arguments, char *comment){ Oid oid; /* Look up the procedure */ oid = LookupFuncNameTypeNames(function, arguments, false); /* Now, validate the user's ability to comment on this function */ if (!pg_proc_ownercheck(oid, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC, NameListToString(function)); /* Call CreateComments() to create/drop the comments */ CreateComments(oid, RelOid_pg_proc, 0, comment);}/* * CommentOperator -- * * This routine is used to allow a user to provide comments on an * operator. The operator for commenting is determined by both * 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 voidCommentOperator(List *opername, List *arguments, char *comment){ TypeName *typenode1 = (TypeName *) lfirst(arguments); TypeName *typenode2 = (TypeName *) lsecond(arguments); Oid oid; Oid classoid; /* Look up the operator */ oid = LookupOperNameTypeNames(opername, typenode1, typenode2, false); /* Valid user's ability to comment on this operator */ if (!pg_oper_ownercheck(oid, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPER, NameListToString(opername)); /* pg_operator doesn't have a hard-coded OID, so must look it up */ classoid = get_system_catalog_relid(OperatorRelationName); /* Call CreateComments() to create/drop the comments */ CreateComments(oid, classoid, 0, comment);}/* * CommentTrigger -- * * This routine is used to allow a user to provide comments on a * trigger event. The trigger for commenting is determined by both * its name and the relation to which it refers. The arguments to this * function are the trigger name and relation name (merged into a qualified * name), and the comment to add/drop. */static voidCommentTrigger(List *qualname, char *comment){ int nnames; List *relname; char *trigname; RangeVar *rel; Relation pg_trigger, relation; HeapTuple triggertuple; SysScanDesc scan; ScanKeyData entry[2]; Oid oid; /* Separate relname and trig name */ nnames = length(qualname); if (nnames < 2) /* parser messed up */ elog(ERROR, "must specify relation and trigger"); relname = ltruncate(nnames - 1, listCopy(qualname)); trigname = strVal(llast(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 trigger tuple from pg_trigger. There can be only one * because of the unique index. */ pg_trigger = heap_openr(TriggerRelationName, AccessShareLock); ScanKeyEntryInitialize(&entry[0], 0x0, Anum_pg_trigger_tgrelid, F_OIDEQ, ObjectIdGetDatum(RelationGetRelid(relation))); ScanKeyEntryInitialize(&entry[1], 0x0, Anum_pg_trigger_tgname, F_NAMEEQ, CStringGetDatum(trigname)); scan = systable_beginscan(pg_trigger, TriggerRelidNameIndex, 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); /* Create the comment with the pg_trigger oid */ CreateComments(oid, RelationGetRelid(pg_trigger), 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 = length(qualname); if (nnames < 2) /* parser messed up */ elog(ERROR, "must specify relation and constraint"); relName = ltruncate(nnames - 1, listCopy(qualname)); conName = strVal(llast(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_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)) 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)))); /* 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);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?