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

📄 rewritedefine.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
				ereport(ERROR,						(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),				  errmsg("SELECT rule's target list has too many entries")));			attr = event_relation->rd_att->attrs[i - 1];			attname = NameStr(attr->attname);			/*			 * Disallow dropped columns in the relation.  This won't happen in			 * the cases we actually care about (namely creating a view via			 * CREATE TABLE then CREATE RULE).	Trying to cope with it is much			 * more trouble than it's worth, because we'd have to modify the			 * rule to insert dummy NULLs at the right positions.			 */			if (attr->attisdropped)				ereport(ERROR,						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),						 errmsg("cannot convert relation containing dropped columns to view")));			if (strcmp(tle->resname, attname) != 0)				ereport(ERROR,						(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),						 errmsg("SELECT rule's target entry %d has different column name from \"%s\"", i, attname)));			if (attr->atttypid != exprType((Node *) tle->expr))				ereport(ERROR,						(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),						 errmsg("SELECT rule's target entry %d has different type from column \"%s\"", i, attname)));			/*			 * Allow typmods to be different only if one of them is -1, ie,			 * "unspecified".  This is necessary for cases like "numeric",			 * where the table will have a filled-in default length but the			 * select rule's expression will probably have typmod = -1.			 */			tletypmod = exprTypmod((Node *) tle->expr);			if (attr->atttypmod != tletypmod &&				attr->atttypmod != -1 && tletypmod != -1)				ereport(ERROR,						(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),						 errmsg("SELECT rule's target entry %d has different size from column \"%s\"", i, attname)));		}		if (i != event_relation->rd_att->natts)			ereport(ERROR,					(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),				   errmsg("SELECT rule's target list has too few entries")));		/*		 * ... there must not be another ON SELECT rule already ...		 */		if (!replace && event_relation->rd_rules != NULL)		{			for (i = 0; i < event_relation->rd_rules->numLocks; i++)			{				RewriteRule *rule;				rule = event_relation->rd_rules->rules[i];				if (rule->event == CMD_SELECT)					ereport(ERROR,						  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),						   errmsg("\"%s\" is already a view",								  RelationGetRelationName(event_relation))));			}		}		/*		 * ... and finally the rule must be named _RETURN.		 */		if (strcmp(stmt->rulename, ViewSelectRuleName) != 0)		{			/*			 * In versions before 7.3, the expected name was _RETviewname. For			 * backwards compatibility with old pg_dump output, accept that			 * and silently change it to _RETURN.  Since this is just a quick			 * backwards-compatibility hack, limit the number of characters			 * checked to a few less than NAMEDATALEN; this saves having to			 * worry about where a multibyte character might have gotten			 * truncated.			 */			if (strncmp(stmt->rulename, "_RET", 4) != 0 ||				strncmp(stmt->rulename + 4, event_obj->relname,						NAMEDATALEN - 4 - 4) != 0)				ereport(ERROR,						(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),						 errmsg("view rule for \"%s\" must be named \"%s\"",								event_obj->relname, ViewSelectRuleName)));			stmt->rulename = pstrdup(ViewSelectRuleName);		}		/*		 * Are we converting a relation to a view?		 *		 * If so, check that the relation is empty because the storage for the		 * relation is going to be deleted.  Also insist that the rel not have		 * any triggers, indexes, or child tables.		 */		if (event_relation->rd_rel->relkind != RELKIND_VIEW)		{			HeapScanDesc scanDesc;			scanDesc = heap_beginscan(event_relation, SnapshotNow, 0, NULL);			if (heap_getnext(scanDesc, ForwardScanDirection) != NULL)				ereport(ERROR,						(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),						 errmsg("could not convert table \"%s\" to a view because it is not empty",								event_obj->relname)));			heap_endscan(scanDesc);			if (event_relation->rd_rel->reltriggers != 0)				ereport(ERROR,						(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),						 errmsg("could not convert table \"%s\" to a view because it has triggers",								event_obj->relname),						 errhint("In particular, the table may not be involved in any foreign key relationships.")));			if (event_relation->rd_rel->relhasindex)				ereport(ERROR,						(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),						 errmsg("could not convert table \"%s\" to a view because it has indexes",								event_obj->relname)));			if (event_relation->rd_rel->relhassubclass)				ereport(ERROR,						(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),						 errmsg("could not convert table \"%s\" to a view because it has child tables",								event_obj->relname)));			RelisBecomingView = true;		}	}	/*	 * This rule is allowed - prepare to install it.	 */	event_attno = -1;	/*	 * We want the rule's table references to be checked as though by the rule	 * owner, not the user referencing the rule.  Therefore, scan through the	 * rule's rtables and set the checkAsUser field on all rtable entries.  We	 * have to look at event_qual as well, in case it contains sublinks.	 */	foreach(l, action)	{		query = (Query *) lfirst(l);		setRuleCheckAsUser_Query(query, GetUserId());	}	setRuleCheckAsUser_Expr(event_qual, GetUserId());	/* discard rule if it's null action and not INSTEAD; it's a no-op */	if (action != NIL || is_instead)	{		ruleId = InsertRule(stmt->rulename,							event_type,							ev_relid,							event_attno,							is_instead,							event_qual,							action,							replace);		/*		 * Set pg_class 'relhasrules' field TRUE for event relation. If		 * appropriate, also modify the 'relkind' field to show that the		 * relation is now a view.		 *		 * Important side effect: an SI notice is broadcast to force all		 * backends (including me!) to update relcache entries with the new		 * rule.		 */		SetRelationRuleStatus(ev_relid, true, RelisBecomingView);	}	/*	 * IF the relation is becoming a view, delete the storage files associated	 * with it.  NB: we had better have AccessExclusiveLock to do this ...	 *	 * XXX what about getting rid of its TOAST table?  For now, we don't.	 */	if (RelisBecomingView)	{		RelationOpenSmgr(event_relation);		smgrscheduleunlink(event_relation->rd_smgr, event_relation->rd_istemp);	}	/* Close rel, but keep lock till commit... */	heap_close(event_relation, NoLock);}/* * setRuleCheckAsUser_Query *		Recursively scan a query and set the checkAsUser field to the *		given userid in all rtable entries. * * Note: for a view (ON SELECT rule), the checkAsUser field of the *OLD* * RTE entry will be overridden when the view rule is expanded, and the * checkAsUser field of the *NEW* entry is irrelevant because that entry's * requiredPerms bits will always be zero.	However, for other types of rules * it's important to set these fields to match the rule owner.  So we just set * them always. */static voidsetRuleCheckAsUser_Query(Query *qry, Oid userid){	ListCell   *l;	/* Set all the RTEs in this query node */	foreach(l, qry->rtable)	{		RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);		if (rte->rtekind == RTE_SUBQUERY)		{			/* Recurse into subquery in FROM */			setRuleCheckAsUser_Query(rte->subquery, userid);		}		else			rte->checkAsUser = userid;	}	/* If there are sublinks, search for them and process their RTEs */	/* ignore subqueries in rtable because we already processed them */	if (qry->hasSubLinks)		query_tree_walker(qry, setRuleCheckAsUser_walker, (void *) &userid,						  QTW_IGNORE_RT_SUBQUERIES);}/* * Expression-tree walker to find sublink queries */static voidsetRuleCheckAsUser_Expr(Node *node, Oid userid){	(void) setRuleCheckAsUser_walker(node, &userid);}static boolsetRuleCheckAsUser_walker(Node *node, Oid *context){	if (node == NULL)		return false;	if (IsA(node, Query))	{		Query	   *qry = (Query *) node;		setRuleCheckAsUser_Query(qry, *context);		return false;	}	return expression_tree_walker(node, setRuleCheckAsUser_walker,								  (void *) context);}/* * Rename an existing rewrite rule. * * This is unused code at the moment. */voidRenameRewriteRule(Oid owningRel, const char *oldName,				  const char *newName){	Relation	pg_rewrite_desc;	HeapTuple	ruletup;	pg_rewrite_desc = heap_open(RewriteRelationId, RowExclusiveLock);	ruletup = SearchSysCacheCopy(RULERELNAME,								 ObjectIdGetDatum(owningRel),								 PointerGetDatum(oldName),								 0, 0);	if (!HeapTupleIsValid(ruletup))		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_OBJECT),				 errmsg("rule \"%s\" for relation \"%s\" does not exist",						oldName, get_rel_name(owningRel))));	/* should not already exist */	if (IsDefinedRewriteRule(owningRel, newName))		ereport(ERROR,				(errcode(ERRCODE_DUPLICATE_OBJECT),				 errmsg("rule \"%s\" for relation \"%s\" already exists",						newName, get_rel_name(owningRel))));	namestrcpy(&(((Form_pg_rewrite) GETSTRUCT(ruletup))->rulename), newName);	simple_heap_update(pg_rewrite_desc, &ruletup->t_self, ruletup);	/* keep system catalog indexes current */	CatalogUpdateIndexes(pg_rewrite_desc, ruletup);	heap_freetuple(ruletup);	heap_close(pg_rewrite_desc, RowExclusiveLock);}

⌨️ 快捷键说明

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