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 + -
显示快捷键?