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

📄 rewritehandler.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 5 页
字号:
/*------------------------------------------------------------------------- * * rewriteHandler.c * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $Header: /usr/local/cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.48 1999/07/11 17:54:30 tgl Exp $ * *------------------------------------------------------------------------- */#include <string.h>#include "postgres.h"#include "miscadmin.h"#include "utils/palloc.h"#include "utils/elog.h"#include "utils/rel.h"#include "nodes/pg_list.h"#include "nodes/primnodes.h"#include "nodes/relation.h"#include "parser/parsetree.h"	/* for parsetree manipulation */#include "parser/parse_relation.h"#include "nodes/parsenodes.h"/***S*I***/#include "parser/parse_node.h"#include "parser/parse_target.h"#include "parser/analyze.h"#include "optimizer/clauses.h"#include "optimizer/prep.h"#include "rewrite/rewriteSupport.h"#include "rewrite/rewriteHandler.h"#include "rewrite/rewriteManip.h"#include "rewrite/locks.h"#include "commands/creatinh.h"#include "access/heapam.h"#include "utils/lsyscache.h"#include "utils/syscache.h"#include "utils/acl.h"#include "catalog/pg_shadow.h"#include "catalog/pg_type.h"static RewriteInfo *gatherRewriteMeta(Query *parsetree,				  Query *rule_action,				  Node *rule_qual,				  int rt_index,				  CmdType event,				  bool *instead_flag);static bool rangeTableEntry_used(Node *node, int rt_index, int sublevels_up);static bool attribute_used(Node *node, int rt_index, int attno, int sublevels_up);static void modifyAggrefUplevel(Node *node);static void modifyAggrefChangeVarnodes(Node **nodePtr, int rt_index, int new_index, int sublevels_up);static void modifyAggrefDropQual(Node **nodePtr, Node *orignode, Expr *expr);static SubLink *modifyAggrefMakeSublink(Expr *origexp, Query *parsetree);static void modifyAggrefQual(Node **nodePtr, Query *parsetree);static bool checkQueryHasAggs(Node *node);static bool checkQueryHasAggs_walker(Node *node, void *context);static bool checkQueryHasSubLink(Node *node);static bool checkQueryHasSubLink_walker(Node *node, void *context);static Query *fireRIRrules(Query *parsetree);static Query *Except_Intersect_Rewrite(Query *parsetree);static void check_targetlists_are_compatible(List *prev_target,											 List *current_target);static void create_intersect_list(Node *ptr, List **intersect_list);static Node *intersect_tree_analyze(Node *tree, Node *first_select,									Node *parsetree);/* * gatherRewriteMeta - *	  Gather meta information about parsetree, and rule. Fix rule body *	  and qualifier so that they can be mixed with the parsetree and *	  maintain semantic validity */static RewriteInfo *gatherRewriteMeta(Query *parsetree,				  Query *rule_action,				  Node *rule_qual,				  int rt_index,				  CmdType event,				  bool *instead_flag){	RewriteInfo *info;	int			rt_length;	int			result_reln;	info = (RewriteInfo *) palloc(sizeof(RewriteInfo));	info->rt_index = rt_index;	info->event = event;	info->instead_flag = *instead_flag;	info->rule_action = (Query *) copyObject(rule_action);	info->rule_qual = (Node *) copyObject(rule_qual);	if (info->rule_action == NULL)		info->nothing = TRUE;	else	{		info->nothing = FALSE;		info->action = info->rule_action->commandType;		info->current_varno = rt_index;		info->rt = parsetree->rtable;		rt_length = length(info->rt);		info->rt = nconc(info->rt, copyObject(info->rule_action->rtable));		info->new_varno = PRS2_NEW_VARNO + rt_length;		OffsetVarNodes(info->rule_action->qual, rt_length, 0);		OffsetVarNodes((Node *) info->rule_action->targetList, rt_length, 0);		OffsetVarNodes(info->rule_qual, rt_length, 0);		ChangeVarNodes((Node *) info->rule_action->qual,					   PRS2_CURRENT_VARNO + rt_length, rt_index, 0);		ChangeVarNodes((Node *) info->rule_action->targetList,					   PRS2_CURRENT_VARNO + rt_length, rt_index, 0);		ChangeVarNodes(info->rule_qual,					   PRS2_CURRENT_VARNO + rt_length, rt_index, 0);		/*		 * bug here about replace CURRENT  -- sort of replace current is		 * deprecated now so this code shouldn't really need to be so		 * clutzy but.....		 */		if (info->action != CMD_SELECT)		{						/* i.e update XXXXX */			int			new_result_reln = 0;			result_reln = info->rule_action->resultRelation;			switch (result_reln)			{				case PRS2_CURRENT_VARNO:					new_result_reln = rt_index;					break;				case PRS2_NEW_VARNO:	/* XXX */				default:					new_result_reln = result_reln + rt_length;					break;			}			info->rule_action->resultRelation = new_result_reln;		}	}	return info;}/* * rangeTableEntry_used - *	we need to process a RTE for RIR rules only if it is *	referenced somewhere in var nodes of the query. */static boolrangeTableEntry_used(Node *node, int rt_index, int sublevels_up){	if (node == NULL)		return FALSE;	switch (nodeTag(node))	{		case T_TargetEntry:			{				TargetEntry *tle = (TargetEntry *) node;				return rangeTableEntry_used(											(Node *) (tle->expr),											rt_index,											sublevels_up);			}			break;		case T_Aggref:			{				Aggref	   *aggref = (Aggref *) node;				return rangeTableEntry_used(											(Node *) (aggref->target),											rt_index,											sublevels_up);			}			break;		case T_GroupClause:			return FALSE;		case T_Expr:			{				Expr	   *exp = (Expr *) node;				return rangeTableEntry_used(											(Node *) (exp->args),											rt_index,											sublevels_up);			}			break;		case T_Iter:			{				Iter	   *iter = (Iter *) node;				return rangeTableEntry_used(											(Node *) (iter->iterexpr),											rt_index,											sublevels_up);			}			break;		case T_ArrayRef:			{				ArrayRef   *ref = (ArrayRef *) node;				if (rangeTableEntry_used(										 (Node *) (ref->refupperindexpr),										 rt_index,										 sublevels_up))					return TRUE;				if (rangeTableEntry_used(										 (Node *) (ref->reflowerindexpr),										 rt_index,										 sublevels_up))					return TRUE;				if (rangeTableEntry_used(										 (Node *) (ref->refexpr),										 rt_index,										 sublevels_up))					return TRUE;				if (rangeTableEntry_used(										 (Node *) (ref->refassgnexpr),										 rt_index,										 sublevels_up))					return TRUE;				return FALSE;			}			break;		case T_Var:			{				Var		   *var = (Var *) node;				if (var->varlevelsup == sublevels_up)					return var->varno == rt_index;				else					return FALSE;			}			break;		case T_Param:			return FALSE;		case T_Const:			return FALSE;		case T_List:			{				List	   *l;				foreach(l, (List *) node)				{					if (rangeTableEntry_used(											 (Node *) lfirst(l),											 rt_index,											 sublevels_up))						return TRUE;				}				return FALSE;			}			break;		case T_SubLink:			{				SubLink    *sub = (SubLink *) node;				if (rangeTableEntry_used(										 (Node *) (sub->lefthand),										 rt_index,										 sublevels_up))					return TRUE;				if (rangeTableEntry_used(										 (Node *) (sub->subselect),										 rt_index,										 sublevels_up + 1))					return TRUE;				return FALSE;			}			break;		case T_CaseExpr:			{				CaseExpr   *exp = (CaseExpr *) node;				if (rangeTableEntry_used(										 (Node *) (exp->args),										 rt_index,										 sublevels_up))					return TRUE;				if (rangeTableEntry_used(										 (Node *) (exp->defresult),										 rt_index,										 sublevels_up))					return TRUE;				return FALSE;			}			break;		case T_CaseWhen:			{				CaseWhen   *when = (CaseWhen *) node;				if (rangeTableEntry_used(										 (Node *) (when->expr),										 rt_index,										 sublevels_up))					return TRUE;				if (rangeTableEntry_used(										 (Node *) (when->result),										 rt_index,										 sublevels_up))					return TRUE;				return FALSE;			}			break;		case T_Query:			{				Query	   *qry = (Query *) node;				if (rangeTableEntry_used(										 (Node *) (qry->targetList),										 rt_index,										 sublevels_up))					return TRUE;				if (rangeTableEntry_used(										 (Node *) (qry->qual),										 rt_index,										 sublevels_up))					return TRUE;				if (rangeTableEntry_used(										 (Node *) (qry->havingQual),										 rt_index,										 sublevels_up))					return TRUE;				return FALSE;			}			break;		default:			elog(NOTICE, "unknown node tag %d in rangeTableEntry_used()", nodeTag(node));			elog(NOTICE, "Node is: %s", nodeToString(node));			break;	}	return FALSE;}/* * attribute_used - *	Check if a specific attribute number of a RTE is used *	somewhere in the query */static boolattribute_used(Node *node, int rt_index, int attno, int sublevels_up){	if (node == NULL)		return FALSE;	switch (nodeTag(node))	{		case T_TargetEntry:			{				TargetEntry *tle = (TargetEntry *) node;				return attribute_used(									  (Node *) (tle->expr),									  rt_index,									  attno,									  sublevels_up);			}			break;		case T_Aggref:			{				Aggref	   *aggref = (Aggref *) node;				return attribute_used(									  (Node *) (aggref->target),									  rt_index,									  attno,									  sublevels_up);			}			break;		case T_GroupClause:			return FALSE;		case T_Expr:			{				Expr	   *exp = (Expr *) node;				return attribute_used(									  (Node *) (exp->args),									  rt_index,									  attno,									  sublevels_up);			}			break;		case T_Iter:			{				Iter	   *iter = (Iter *) node;				return attribute_used(									  (Node *) (iter->iterexpr),									  rt_index,									  attno,									  sublevels_up);			}			break;		case T_ArrayRef:			{				ArrayRef   *ref = (ArrayRef *) node;				if (attribute_used(								   (Node *) (ref->refupperindexpr),								   rt_index,								   attno,								   sublevels_up))					return TRUE;				if (attribute_used(								   (Node *) (ref->reflowerindexpr),								   rt_index,								   attno,								   sublevels_up))					return TRUE;				if (attribute_used(								   (Node *) (ref->refexpr),								   rt_index,								   attno,								   sublevels_up))					return TRUE;				if (attribute_used(								   (Node *) (ref->refassgnexpr),								   rt_index,								   attno,								   sublevels_up))					return TRUE;				return FALSE;			}			break;		case T_Var:			{				Var		   *var = (Var *) node;				if (var->varlevelsup == sublevels_up)					return var->varno == rt_index;				else					return FALSE;			}			break;		case T_Param:			return FALSE;		case T_Const:			return FALSE;		case T_List:			{				List	   *l;				foreach(l, (List *) node)				{					if (attribute_used(									   (Node *) lfirst(l),									   rt_index,									   attno,									   sublevels_up))						return TRUE;				}				return FALSE;			}			break;		case T_SubLink:			{				SubLink    *sub = (SubLink *) node;				if (attribute_used(								   (Node *) (sub->lefthand),								   rt_index,								   attno,								   sublevels_up))					return TRUE;				if (attribute_used(								   (Node *) (sub->subselect),								   rt_index,								   attno,								   sublevels_up + 1))					return TRUE;				return FALSE;			}			break;		case T_Query:			{				Query	   *qry = (Query *) node;				if (attribute_used(								   (Node *) (qry->targetList),								   rt_index,								   attno,								   sublevels_up))					return TRUE;				if (attribute_used(								   (Node *) (qry->qual),								   rt_index,								   attno,								   sublevels_up))					return TRUE;				if (attribute_used(								   (Node *) (qry->havingQual),								   rt_index,								   attno,								   sublevels_up))					return TRUE;				return FALSE;			}			break;		default:			elog(NOTICE, "unknown node tag %d in attribute_used()", nodeTag(node));			elog(NOTICE, "Node is: %s", nodeToString(node));			break;	}	return FALSE;}/* * modifyAggrefUplevel - *	In the newly created sublink for an aggregate column used in *	the qualification, we must adjust the varlevelsup in all the *	var nodes. */static voidmodifyAggrefUplevel(Node *node){	if (node == NULL)		return;	switch (nodeTag(node))	{		case T_TargetEntry:			{				TargetEntry *tle = (TargetEntry *) node;				modifyAggrefUplevel(									(Node *) (tle->expr));			}			break;		case T_Aggref:			{				Aggref	   *aggref = (Aggref *) node;				modifyAggrefUplevel(									(Node *) (aggref->target));			}

⌨️ 快捷键说明

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