⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 comment.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 3 页
字号:
/*------------------------------------------------------------------------- * * comment.c * * PostgreSQL object comments utility code. * * Copyright (c) 1996-2005, PostgreSQL Global Development Group * * IDENTIFICATION *	  $PostgreSQL: pgsql/src/backend/commands/comment.c,v 1.84.2.1 2005/11/22 18:23:06 momjian Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include "access/genam.h"#include "access/heapam.h"#include "catalog/indexing.h"#include "catalog/namespace.h"#include "catalog/pg_cast.h"#include "catalog/pg_constraint.h"#include "catalog/pg_conversion.h"#include "catalog/pg_database.h"#include "catalog/pg_description.h"#include "catalog/pg_language.h"#include "catalog/pg_largeobject.h"#include "catalog/pg_namespace.h"#include "catalog/pg_opclass.h"#include "catalog/pg_operator.h"#include "catalog/pg_proc.h"#include "catalog/pg_rewrite.h"#include "catalog/pg_trigger.h"#include "catalog/pg_type.h"#include "commands/comment.h"#include "commands/dbcommands.h"#include "miscadmin.h"#include "parser/parse_func.h"#include "parser/parse_oper.h"#include "parser/parse_type.h"#include "utils/acl.h"#include "utils/builtins.h"#include "utils/fmgroids.h"#include "utils/lsyscache.h"#include "utils/syscache.h"/* * Static Function Prototypes -- * * The following protoypes are declared static so as not to conflict * with any other routines outside this module. These routines are * called by the public function CommentObject() routine to create * the appropriate comment for the specific object type. */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);static void CommentProc(List *function, List *arguments, char *comment);static void CommentOperator(List *opername, List *arguments, char *comment);static void CommentTrigger(List *qualname, char *comment);static void CommentConstraint(List *qualname, char *comment);static void CommentConversion(List *qualname, char *comment);static void CommentLanguage(List *qualname, char *comment);static void CommentOpClass(List *qualname, List *arguments, char *comment);static void CommentLargeObject(List *qualname, char *comment);static void CommentCast(List *qualname, List *arguments, char *comment);/* * CommentObject -- * * This routine is used to add the associated comment into * pg_description for the object specified by the given SQL command. */voidCommentObject(CommentStmt *stmt){	switch (stmt->objtype)	{		case OBJECT_INDEX:		case OBJECT_SEQUENCE:		case OBJECT_TABLE:		case OBJECT_VIEW:			CommentRelation(stmt->objtype, stmt->objname, stmt->comment);			break;		case OBJECT_COLUMN:			CommentAttribute(stmt->objname, stmt->comment);			break;		case OBJECT_DATABASE:			CommentDatabase(stmt->objname, stmt->comment);			break;		case OBJECT_RULE:			CommentRule(stmt->objname, stmt->comment);			break;		case OBJECT_TYPE:			CommentType(stmt->objname, stmt->comment);			break;		case OBJECT_AGGREGATE:			CommentAggregate(stmt->objname, stmt->objargs, stmt->comment);			break;		case OBJECT_FUNCTION:			CommentProc(stmt->objname, stmt->objargs, stmt->comment);			break;		case OBJECT_OPERATOR:			CommentOperator(stmt->objname, stmt->objargs, stmt->comment);			break;		case OBJECT_TRIGGER:			CommentTrigger(stmt->objname, stmt->comment);			break;		case OBJECT_SCHEMA:			CommentNamespace(stmt->objname, stmt->comment);			break;		case OBJECT_CONSTRAINT:			CommentConstraint(stmt->objname, stmt->comment);			break;		case OBJECT_CONVERSION:			CommentConversion(stmt->objname, stmt->comment);			break;		case OBJECT_LANGUAGE:			CommentLanguage(stmt->objname, stmt->comment);			break;		case OBJECT_OPCLASS:			CommentOpClass(stmt->objname, stmt->objargs, stmt->comment);			break;		case OBJECT_LARGEOBJECT:			CommentLargeObject(stmt->objname, stmt->comment);			break;		case OBJECT_CAST:			CommentCast(stmt->objname, stmt->objargs, stmt->comment);			break;		default:			elog(ERROR, "unrecognized object type: %d",				 (int) stmt->objtype);	}}/* * CreateComments -- * * Create a comment for the specified object descriptor.  Inserts a new * pg_description tuple, or replaces an existing one with the same key. * * If the comment given is null or an empty string, instead delete any * existing comment for the specified key. */voidCreateComments(Oid oid, Oid classoid, int32 subid, char *comment){	Relation	description;	ScanKeyData skey[3];	SysScanDesc sd;	HeapTuple	oldtuple;	HeapTuple	newtuple = NULL;	Datum		values[Natts_pg_description];	char		nulls[Natts_pg_description];	char		replaces[Natts_pg_description];	int			i;	/* Reduce empty-string to NULL case */	if (comment != NULL && strlen(comment) == 0)		comment = NULL;	/* Prepare to form or update a tuple, if necessary */	if (comment != NULL)	{		for (i = 0; i < Natts_pg_description; i++)		{			nulls[i] = ' ';			replaces[i] = 'r';		}		i = 0;		values[i++] = ObjectIdGetDatum(oid);		values[i++] = ObjectIdGetDatum(classoid);		values[i++] = Int32GetDatum(subid);		values[i++] = DirectFunctionCall1(textin, CStringGetDatum(comment));	}	/* Use the index to search for a matching old tuple */	ScanKeyInit(&skey[0],				Anum_pg_description_objoid,				BTEqualStrategyNumber, F_OIDEQ,				ObjectIdGetDatum(oid));	ScanKeyInit(&skey[1],				Anum_pg_description_classoid,				BTEqualStrategyNumber, F_OIDEQ,				ObjectIdGetDatum(classoid));	ScanKeyInit(&skey[2],				Anum_pg_description_objsubid,				BTEqualStrategyNumber, F_INT4EQ,				Int32GetDatum(subid));	description = heap_open(DescriptionRelationId, RowExclusiveLock);	sd = systable_beginscan(description, DescriptionObjIndexId, true,							SnapshotNow, 3, skey);	while ((oldtuple = systable_getnext(sd)) != NULL)	{		/* Found the old tuple, so delete or update it */		if (comment == NULL)			simple_heap_delete(description, &oldtuple->t_self);		else		{			newtuple = heap_modifytuple(oldtuple, RelationGetDescr(description), values,										nulls, replaces);			simple_heap_update(description, &oldtuple->t_self, newtuple);		}		break;					/* Assume there can be only one match */	}	systable_endscan(sd);	/* If we didn't find an old tuple, insert a new one */	if (newtuple == NULL && comment != NULL)	{		newtuple = heap_formtuple(RelationGetDescr(description),								  values, nulls);		simple_heap_insert(description, newtuple);	}	/* Update indexes, if necessary */	if (newtuple != NULL)	{		CatalogUpdateIndexes(description, newtuple);		heap_freetuple(newtuple);	}	/* Done */	heap_close(description, NoLock);}/* * DeleteComments -- remove comments for an object * * If subid is nonzero then only comments matching it will be removed. * If subid is zero, all comments matching the oid/classoid will be removed * (this corresponds to deleting a whole object). */voidDeleteComments(Oid oid, Oid classoid, int32 subid){	Relation	description;	ScanKeyData skey[3];	int			nkeys;	SysScanDesc sd;	HeapTuple	oldtuple;	/* Use the index to search for all matching old tuples */	ScanKeyInit(&skey[0],				Anum_pg_description_objoid,				BTEqualStrategyNumber, F_OIDEQ,				ObjectIdGetDatum(oid));	ScanKeyInit(&skey[1],				Anum_pg_description_classoid,				BTEqualStrategyNumber, F_OIDEQ,				ObjectIdGetDatum(classoid));	if (subid != 0)	{		ScanKeyInit(&skey[2],					Anum_pg_description_objsubid,					BTEqualStrategyNumber, F_INT4EQ,					Int32GetDatum(subid));		nkeys = 3;	}	else		nkeys = 2;	description = heap_open(DescriptionRelationId, RowExclusiveLock);	sd = systable_beginscan(description, DescriptionObjIndexId, true,							SnapshotNow, nkeys, skey);	while ((oldtuple = systable_getnext(sd)) != NULL)		simple_heap_delete(description, &oldtuple->t_self);	/* Done */	systable_endscan(sd);	heap_close(description, RowExclusiveLock);}/* * CommentRelation -- * * This routine is used to add/drop a comment from a relation, where * a relation is a TABLE, SEQUENCE, VIEW or INDEX. The routine simply * finds the relation name by searching the system cache, locating * the appropriate tuple, and inserting a comment using that * tuple's oid. Its parameters are the relation name and comments. */static voidCommentRelation(int objtype, List *relname, char *comment){	Relation	relation;	RangeVar   *tgtrel;	tgtrel = makeRangeVarFromNameList(relname);	/*	 * Open the relation.  We do this mainly to acquire a lock that ensures no	 * one else drops the relation before we commit.  (If they did, they'd	 * fail to remove the entry we are about to make in pg_description.)	 */	relation = relation_openrv(tgtrel, AccessShareLock);	/* Check object security */	if (!pg_class_ownercheck(RelationGetRelid(relation), GetUserId()))		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,					   RelationGetRelationName(relation));	/* Next, verify that the relation type matches the intent */	switch (objtype)	{		case OBJECT_INDEX:			if (relation->rd_rel->relkind != RELKIND_INDEX)				ereport(ERROR,						(errcode(ERRCODE_WRONG_OBJECT_TYPE),						 errmsg("\"%s\" is not an index",								RelationGetRelationName(relation))));			break;		case OBJECT_SEQUENCE:			if (relation->rd_rel->relkind != RELKIND_SEQUENCE)				ereport(ERROR,						(errcode(ERRCODE_WRONG_OBJECT_TYPE),						 errmsg("\"%s\" is not a sequence",								RelationGetRelationName(relation))));			break;		case OBJECT_TABLE:			if (relation->rd_rel->relkind != RELKIND_RELATION)				ereport(ERROR,						(errcode(ERRCODE_WRONG_OBJECT_TYPE),						 errmsg("\"%s\" is not a table",								RelationGetRelationName(relation))));			break;		case OBJECT_VIEW:			if (relation->rd_rel->relkind != RELKIND_VIEW)				ereport(ERROR,						(errcode(ERRCODE_WRONG_OBJECT_TYPE),						 errmsg("\"%s\" is not a view",								RelationGetRelationName(relation))));			break;	}	/* Create the comment using the relation's oid */	CreateComments(RelationGetRelid(relation), RelationRelationId,				   0, comment);	/* Done, but hold lock until commit */	relation_close(relation, NoLock);}/* * CommentAttribute -- * * This routine is used to add/drop a comment from an attribute * such as a table's column. The routine will check security * restrictions and then attempt to look up the specified * attribute. If successful, a comment is added/dropped, else an * ereport() exception is thrown.	The parameters are the relation * and attribute names, and the comment */static voidCommentAttribute(List *qualname, char *comment){	int			nnames;	List	   *relname;	char	   *attrname;	RangeVar   *rel;	Relation	relation;	AttrNumber	attnum;	/* Separate relname and attr name */	nnames = list_length(qualname);	if (nnames < 2)				/* parser messed up */		elog(ERROR, "must specify relation and attribute");	relname = list_truncate(list_copy(qualname), nnames - 1);	attrname = strVal(lfirst(list_tail(qualname)));	/* Open the containing relation to ensure it won't go away meanwhile */	rel = makeRangeVarFromNameList(relname);	relation = relation_openrv(rel, AccessShareLock);	/* Check object security */	if (!pg_class_ownercheck(RelationGetRelid(relation), GetUserId()))		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -