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

📄 recipe.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 3 页
字号:
/*------------------------------------------------------------------------- * * recipe.c *	  routines for handling execution of Tioga recipes * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $Header: /usr/local/cvsroot/pgsql/src/backend/commands/_deadcode/recipe.c,v 1.4.2.1 1999/08/02 05:57:01 scrappy Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include "catalog/pg_type.h"#include "commands/recipe.h"#include "executor/executor.h"#include "libpq/libpq-be.h"#include "nodes/execnodes.h"#include "nodes/makefuncs.h"#include "nodes/parsenodes.h"#include "nodes/plannodes.h"#include "optimizer/planner.h"#include "parser/parse_node.h"#include "rewrite/rewriteHandler.h"#include "rewrite/rewriteManip.h"#include "tcop/dest.h"#include "tcop/pquery.h"#include "utils/builtins.h"#include "utils/relcache.h"/* from tcop/postgres.c */extern CommandDest whereToSendOutput;#ifndef TIOGAvoidbeginRecipe(RecipeStmt *stmt){	elog(NOTICE, "You must compile with TIOGA defined in order to use recipes\n");}#else#include "tioga/tgRecipe.h"#define DEBUG_RECIPE 1/* structure to keep track of the tee node plans */typedef struct _teePlanInfo{	char	   *tpi_relName;	Query	   *tpi_parsetree;	Plan	   *tpi_plan;}			TeePlanInfo;typedef struct _teeInfo{	int			num;	TeePlanInfo *val;}			TeeInfo;QueryTreeList *appendQlist(QueryTreeList * q1, QueryTreeList * q2);void		OffsetVarAttno(Node *node, int varno, int offset);static void appendTeeQuery(TeeInfo * teeInfo,			   QueryTreeList * q,			   char *teeNodeName);static Plan *replaceTeeScans(Plan *plan,				Query *parsetree,				TeeInfo * teeInfo);static void replaceSeqScan(Plan *plan,			   Plan *parent,			   int rt_ind,			   Plan *tplan);static void tg_rewriteQuery(TgRecipe * r, TgNode * n,				QueryTreeList * q,				QueryTreeList * inputQlist);static Node *tg_replaceNumberedParam(Node *expression,						int pnum,						int rt_ind,						char *teeRelName);static Node *tg_rewriteParamsInExpr(Node *expression,					   QueryTreeList * inputQlist);static QueryTreeList *tg_parseSubQuery(TgRecipe * r,				 TgNode * n,				 TeeInfo * teeInfo);static QueryTreeList *tg_parseTeeNode(TgRecipe * r,				TgNode * n,				int i,				QueryTreeList * qList,				TeeInfo * teeInfo);/*   The Tioga recipe rewrite algorithm:   To parse a Tioga recipe, we start from an eye node and go backwards through   its input nodes.  To rewrite a Tioga node, we do the following:	  1) parse the node we're at in the standard way (calling parser() )	  2) rewrite its input nodes recursively using Tioga rewrite	  3) now, with the rewritten input parse trees and the original parse tree		 of the node,  we rewrite the the node.		 To do the rewrite, we use the target lists, range tables, and		 qualifications of the input parse trees*//* * beginRecipe: *	  this is the main function to recipe execution *	 this function is invoked for EXECUTE RECIPE ...  statements * *	takes in a RecipeStmt structure from the parser * and returns a list of cursor names */voidbeginRecipe(RecipeStmt *stmt){	TgRecipe   *r;	int			i,				numTees;	QueryTreeList *qList;	char		portalName[1024];	Plan	   *plan;	TupleDesc	attinfo;	QueryDesc  *queryDesc;	Query	   *parsetree;	TeeInfo    *teeInfo;	/*	 * retrieveRecipe() reads the recipe from the database and returns a	 * TgRecipe* structure we can work with	 */	r = retrieveRecipe(stmt->recipeName);	if (r == NULL)		return;	/* find the number of tees in the recipe */	numTees = r->tees->num;	if (numTees > 0)	{		/* allocate a teePlan structure */		teeInfo = (TeeInfo *) malloc(sizeof(TeeInfo));		teeInfo->num = numTees;		teeInfo->val = (TeePlanInfo *) malloc(numTees * sizeof(TeePlanInfo));		for (i = 0; i < numTees; i++)		{			teeInfo->val[i].tpi_relName = r->tees->val[i]->nodeName;			teeInfo->val[i].tpi_parsetree = NULL;			teeInfo->val[i].tpi_plan = NULL;		}	}	else		teeInfo = NULL;	/*	 * for each viewer in the recipe, go backwards from each viewer input	 * and generate a plan.  Attach the plan to cursors.	 */	for (i = 0; i < r->eyes->num; i++)	{		TgNodePtr	e;		e = r->eyes->val[i];		if (e->inNodes->num > 1)		{			elog(NOTICE,				 "beginRecipe: Currently eyes cannot have more than one input");		}		if (e->inNodes->num == 0)		{			/* no input to this eye, skip it */			continue;		}#ifdef DEBUG_RECIPE		elog(NOTICE, "beginRecipe: eyes[%d] = %s\n", i, e->nodeName);#endif	 /* DEBUG_RECIPE */		qList = tg_parseSubQuery(r, e->inNodes->val[0], teeInfo);		if (qList == NULL)		{			/* eye is directly connected to a tee node */			/* XXX TODO: handle this case */		}		/* now, plan the queries */		/*		 * should really do everything pg_plan() does, but for now, we		 * skip the rule rewrite and time qual stuff		 */		/* ----------------------------------------------------------		 * 1) plan the main query, everything from an eye node back to			 a Tee		 * ---------------------------------------------------------- */		parsetree = qList->qtrees[0];		/*		 * before we plan, we want to see all the changes we did, during		 * the rewrite phase, such as creating the tee tables,		 * setheapoverride() allows us to see the changes		 */		setheapoverride(true);		plan = planner(parsetree);		/* ----------------------------------------------------------		 * 2) plan the tee queries, (subgraphs rooted from a Tee)			 by the time the eye is processed, all tees that contribute			 to that eye will have been included in the teeInfo list		 * ---------------------------------------------------------- */		if (teeInfo)		{			int			t;			Plan	   *tplan;			Tee		   *newplan;			for (t = 0; t < teeInfo->num; t++)			{				if (teeInfo->val[t].tpi_plan == NULL)				{					/* plan it in the usual fashion */					tplan = planner(teeInfo->val[t].tpi_parsetree);					/* now add a tee node to the root of the plan */					elog(NOTICE, "adding tee plan node to the root of the %s\n",						 teeInfo->val[t].tpi_relName);					newplan = (Tee *) makeNode(Tee);					newplan->plan.targetlist = tplan->targetlist;					newplan->plan.qual = NULL;	/* tplan->qual; */					newplan->plan.lefttree = tplan;					newplan->plan.righttree = NULL;					newplan->leftParent = NULL;					newplan->rightParent = NULL;					/*					 * the range table of the tee is the range table of					 * the tplan					 */					newplan->rtentries = teeInfo->val[t].tpi_parsetree->rtable;					strcpy(newplan->teeTableName,						   teeInfo->val[t].tpi_relName);					teeInfo->val[t].tpi_plan = (Plan *) newplan;				}			}			/* ----------------------------------------------------------			 * 3) replace the tee table scans in the main plan with				  actual tee plannodes			 * ---------------------------------------------------------- */			plan = replaceTeeScans(plan, parsetree, teeInfo);		}						/* if (teeInfo) */		setheapoverride(false);		/* define a portal for this viewer input */		/* for now, eyes can only have one input */		snprintf(portalName, 1024, "%s%d", e->nodeName, 0);		queryDesc = CreateQueryDesc(parsetree,									plan,									whereToSendOutput);		/* ----------------		 *		  call ExecStart to prepare the plan for execution		 * ----------------		 */		attinfo = ExecutorStart(queryDesc, NULL);		ProcessPortal(portalName,					  parsetree,					  plan,					  attinfo,					  whereToSendOutput);		elog(NOTICE, "beginRecipe: cursor named %s is now available", portalName);	}}/* * tg_rewriteQuery - *	  r - the recipe being rewritten *	  n - the node that we're current at *	  q - a QueryTree List containing the parse tree of the node *	  inputQlist - the parsetrees of its input nodes, *				   the size of inputQlist must be the same as the *				   number of input nodes.  Some elements in the inpuQlist *				   may be null if the inputs to those nodes are unconnected * *	this is the main routine for rewriting the recipe queries *	the original query tree 'q' is modified */static voidtg_rewriteQuery(TgRecipe * r,				TgNode * n,				QueryTreeList * q,				QueryTreeList * inputQlist){	Query	   *orig;	Query	   *inputQ;	int			i;	List	   *rtable;	List	   *input_rtable;	int			rt_length;	/* orig is the original parse tree of the node */	orig = q->qtrees[0];	/*-------------------------------------------------------------------	   step 1:	   form a combined range table from all the range tables in the original	   query as well as the input nodes	   form a combined qualification from the qual in the original plus	   the quals of the input nodes	  -------------------------------------------------------------------	*/	/* start with the original range table */	rtable = orig->rtable;	rt_length = length(rtable);	for (i = 0; i < n->inNodes->num; i++)	{		if (n->inNodes->val[i] != NULL &&			n->inNodes->val[i]->nodeType != TG_TEE_NODE)		{			inputQ = inputQlist->qtrees[i];			input_rtable = inputQ->rtable;			/*			 * need to offset the var nodes in the qual and targetlist			 * because they are indexed off the original rtable			 */			OffsetVarNodes((Node *) inputQ->qual, rt_length, 0);			OffsetVarNodes((Node *) inputQ->targetList, rt_length, 0);			/* append the range tables from the children nodes	*/			rtable = nconc(rtable, input_rtable);			/*			 * append the qualifications of the child node into the			 * original qual list			 */			AddQual(orig, inputQ->qual);		}	}	orig->rtable = rtable;	/*	 * step 2: rewrite the target list of the original parse tree if there	 * are any references to params, replace them with the appropriate	 * target list entry of the children node	 */	if (orig->targetList != NIL)	{		List	   *tl;		TargetEntry *tle;		foreach(tl, orig->targetList)		{			tle = lfirst(tl);			if (tle->resdom != NULL)				tle->expr = tg_rewriteParamsInExpr(tle->expr, inputQlist);		}	}	/*	 * step 3: rewrite the qual of the original parse tree if there are	 * any references to params, replace them with the appropriate target	 * list entry of the children node	 */	if (orig->qual)	{		if (nodeTag(orig->qual) == T_List)			elog(ERROR, "tg_rewriteQuery: Whoa! why is my qual a List???");		orig->qual = tg_rewriteParamsInExpr(orig->qual, inputQlist);	}	/*	 * at this point, we're done with the rewrite, the querytreelist q has	 * been modified	 */}/* tg_replaceNumberedParam:   this procedure replaces the specified numbered param with a   reference to a range table   this procedure recursively calls itself   it returns a (possibly modified) Node*.*/static Node *tg_replaceNumberedParam(Node *expression,						int pnum,		/* the number of the parameter */						int rt_ind,		/* the range table index */						char *teeRelName)		/* the relname of the tee												 * table */{	TargetEntry *param_tle;	Param	   *p;	Var		   *newVar,			   *oldVar;	if (expression == NULL)		return NULL;	switch (nodeTag(expression))	{		case T_Param:			{				/*				 * the node is a parameter, substitute the entry from the				 * target list of the child that corresponds to the				 * parameter number				 */				p = (Param *) expression;				/* we only deal with the case of numbered parameters */				if (p->paramkind == PARAM_NUM && p->paramid == pnum)				{

⌨️ 快捷键说明

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