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

📄 rewritedefine.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------- * * rewriteDefine.c *	  routines for defining a rewrite rule * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $PostgreSQL: pgsql/src/backend/rewrite/rewriteDefine.c,v 1.107.2.1 2005/11/22 18:23:16 momjian Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include "access/heapam.h"#include "catalog/dependency.h"#include "catalog/indexing.h"#include "catalog/pg_rewrite.h"#include "commands/view.h"#include "miscadmin.h"#include "optimizer/clauses.h"#include "parser/parse_expr.h"#include "parser/parse_relation.h"#include "rewrite/rewriteDefine.h"#include "rewrite/rewriteManip.h"#include "rewrite/rewriteSupport.h"#include "storage/smgr.h"#include "utils/acl.h"#include "utils/builtins.h"#include "utils/lsyscache.h"#include "utils/syscache.h"static void setRuleCheckAsUser_Query(Query *qry, Oid userid);static void setRuleCheckAsUser_Expr(Node *node, Oid userid);static bool setRuleCheckAsUser_walker(Node *node, Oid *context);/* * InsertRule - *	  takes the arguments and inserts them as a row into the system *	  relation "pg_rewrite" */static OidInsertRule(char *rulname,		   int evtype,		   Oid eventrel_oid,		   AttrNumber evslot_index,		   bool evinstead,		   Node *event_qual,		   List *action,		   bool replace){	char	   *evqual = nodeToString(event_qual);	char	   *actiontree = nodeToString((Node *) action);	int			i;	Datum		values[Natts_pg_rewrite];	char		nulls[Natts_pg_rewrite];	char		replaces[Natts_pg_rewrite];	NameData	rname;	Relation	pg_rewrite_desc;	HeapTuple	tup,				oldtup;	Oid			rewriteObjectId;	ObjectAddress myself,				referenced;	bool		is_update = false;	/*	 * Set up *nulls and *values arrays	 */	MemSet(nulls, ' ', sizeof(nulls));	i = 0;	namestrcpy(&rname, rulname);	values[i++] = NameGetDatum(&rname); /* rulename */	values[i++] = ObjectIdGetDatum(eventrel_oid);		/* ev_class */	values[i++] = Int16GetDatum(evslot_index);	/* ev_attr */	values[i++] = CharGetDatum(evtype + '0');	/* ev_type */	values[i++] = BoolGetDatum(evinstead);		/* is_instead */	values[i++] = DirectFunctionCall1(textin, CStringGetDatum(evqual)); /* ev_qual */	values[i++] = DirectFunctionCall1(textin, CStringGetDatum(actiontree));		/* ev_action */	/*	 * Ready to store new pg_rewrite tuple	 */	pg_rewrite_desc = heap_open(RewriteRelationId, RowExclusiveLock);	/*	 * Check to see if we are replacing an existing tuple	 */	oldtup = SearchSysCache(RULERELNAME,							ObjectIdGetDatum(eventrel_oid),							PointerGetDatum(rulname),							0, 0);	if (HeapTupleIsValid(oldtup))	{		if (!replace)			ereport(ERROR,					(errcode(ERRCODE_DUPLICATE_OBJECT),					 errmsg("rule \"%s\" for relation \"%s\" already exists",							rulname, get_rel_name(eventrel_oid))));		/*		 * When replacing, we don't need to replace every attribute		 */		MemSet(replaces, ' ', sizeof(replaces));		replaces[Anum_pg_rewrite_ev_attr - 1] = 'r';		replaces[Anum_pg_rewrite_ev_type - 1] = 'r';		replaces[Anum_pg_rewrite_is_instead - 1] = 'r';		replaces[Anum_pg_rewrite_ev_qual - 1] = 'r';		replaces[Anum_pg_rewrite_ev_action - 1] = 'r';		tup = heap_modifytuple(oldtup, RelationGetDescr(pg_rewrite_desc),							   values, nulls, replaces);		simple_heap_update(pg_rewrite_desc, &tup->t_self, tup);		ReleaseSysCache(oldtup);		rewriteObjectId = HeapTupleGetOid(tup);		is_update = true;	}	else	{		tup = heap_formtuple(pg_rewrite_desc->rd_att, values, nulls);		rewriteObjectId = simple_heap_insert(pg_rewrite_desc, tup);	}	/* Need to update indexes in either case */	CatalogUpdateIndexes(pg_rewrite_desc, tup);	heap_freetuple(tup);	/* If replacing, get rid of old dependencies and make new ones */	if (is_update)		deleteDependencyRecordsFor(RewriteRelationId, rewriteObjectId);	/*	 * Install dependency on rule's relation to ensure it will go away on	 * relation deletion.  If the rule is ON SELECT, make the dependency	 * implicit --- this prevents deleting a view's SELECT rule.  Other kinds	 * of rules can be AUTO.	 */	myself.classId = RewriteRelationId;	myself.objectId = rewriteObjectId;	myself.objectSubId = 0;	referenced.classId = RelationRelationId;	referenced.objectId = eventrel_oid;	referenced.objectSubId = 0;	recordDependencyOn(&myself, &referenced,			 (evtype == CMD_SELECT) ? DEPENDENCY_INTERNAL : DEPENDENCY_AUTO);	/*	 * Also install dependencies on objects referenced in action and qual.	 */	recordDependencyOnExpr(&myself, (Node *) action, NIL,						   DEPENDENCY_NORMAL);	if (event_qual != NULL)	{		/* Find query containing OLD/NEW rtable entries */		Query	   *qry = (Query *) linitial(action);		qry = getInsertSelectQuery(qry, NULL);		recordDependencyOnExpr(&myself, event_qual, qry->rtable,							   DEPENDENCY_NORMAL);	}	heap_close(pg_rewrite_desc, RowExclusiveLock);	return rewriteObjectId;}voidDefineQueryRewrite(RuleStmt *stmt){	RangeVar   *event_obj = stmt->relation;	Node	   *event_qual = stmt->whereClause;	CmdType		event_type = stmt->event;	bool		is_instead = stmt->instead;	bool		replace = stmt->replace;	List	   *action = stmt->actions;	Relation	event_relation;	Oid			ev_relid;	Oid			ruleId;	int			event_attno;	ListCell   *l;	Query	   *query;	AclResult	aclresult;	bool		RelisBecomingView = false;	/*	 * If we are installing an ON SELECT rule, we had better grab	 * AccessExclusiveLock to ensure no SELECTs are currently running on the	 * event relation.	For other types of rules, it might be sufficient to	 * grab ShareLock to lock out insert/update/delete actions.  But for now,	 * let's just grab AccessExclusiveLock all the time.	 */	event_relation = heap_openrv(event_obj, AccessExclusiveLock);	ev_relid = RelationGetRelid(event_relation);	/*	 * Check user has permission to apply rules to this relation.	 */	aclresult = pg_class_aclcheck(ev_relid, GetUserId(), ACL_RULE);	if (aclresult != ACLCHECK_OK)		aclcheck_error(aclresult, ACL_KIND_CLASS,					   RelationGetRelationName(event_relation));	/*	 * No rule actions that modify OLD or NEW	 */	foreach(l, action)	{		query = (Query *) lfirst(l);		if (query->resultRelation == 0)			continue;		/* Don't be fooled by INSERT/SELECT */		if (query != getInsertSelectQuery(query, NULL))			continue;		if (query->resultRelation == PRS2_OLD_VARNO)			ereport(ERROR,					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),					 errmsg("rule actions on OLD are not implemented"),					 errhint("Use views or triggers instead.")));		if (query->resultRelation == PRS2_NEW_VARNO)			ereport(ERROR,					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),					 errmsg("rule actions on NEW are not implemented"),					 errhint("Use triggers instead.")));	}	/*	 * Rules ON SELECT are restricted to view definitions	 */	if (event_type == CMD_SELECT)	{		ListCell   *tllist;		int			i;		/*		 * So there cannot be INSTEAD NOTHING, ...		 */		if (list_length(action) == 0)			ereport(ERROR,					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),			   errmsg("INSTEAD NOTHING rules on SELECT are not implemented"),					 errhint("Use views instead.")));		/*		 * ... there cannot be multiple actions, ...		 */		if (list_length(action) > 1)			ereport(ERROR,					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),					 errmsg("multiple actions for rules on SELECT are not implemented")));		/*		 * ... the one action must be a SELECT, ...		 */		query = (Query *) linitial(action);		if (!is_instead || query->commandType != CMD_SELECT)			ereport(ERROR,					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),				 errmsg("rules on SELECT must have action INSTEAD SELECT")));		/*		 * ... there can be no rule qual, ...		 */		if (event_qual != NULL)			ereport(ERROR,					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),					 errmsg("event qualifications are not implemented for rules on SELECT")));		/*		 * ... the targetlist of the SELECT action must exactly match the		 * event relation, ...		 */		i = 0;		foreach(tllist, query->targetList)		{			TargetEntry *tle = (TargetEntry *) lfirst(tllist);			int32		tletypmod;			Form_pg_attribute attr;			char	   *attname;			if (tle->resjunk)				continue;			i++;			if (i > event_relation->rd_att->natts)

⌨️ 快捷键说明

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