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

📄 analyze.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 3 页
字号:
	extras_before = blist;	extras_after = ilist;	return q;}	/* transformCreateStmt() *//* * transformIndexStmt - *	  transforms the qualification of the index statement */static Query *transformIndexStmt(ParseState *pstate, IndexStmt *stmt){	Query	   *qry;	qry = makeNode(Query);	qry->commandType = CMD_UTILITY;	/* take care of the where clause */	stmt->whereClause = transformWhereClause(pstate, stmt->whereClause, NULL);	qry->hasSubLinks = pstate->p_hasSubLinks;	stmt->rangetable = pstate->p_rtable;	qry->utilityStmt = (Node *) stmt;	return qry;}/* * transformExtendStmt - *	  transform the qualifications of the Extend Index Statement * */static Query *transformExtendStmt(ParseState *pstate, ExtendStmt *stmt){	Query	   *qry;	qry = makeNode(Query);	qry->commandType = CMD_UTILITY;	/* take care of the where clause */	stmt->whereClause = transformWhereClause(pstate, stmt->whereClause, NULL);	qry->hasSubLinks = pstate->p_hasSubLinks;	stmt->rangetable = pstate->p_rtable;	qry->utilityStmt = (Node *) stmt;	return qry;}/* * transformRuleStmt - *	  transform a Create Rule Statement. The actions is a list of parse *	  trees which is transformed into a list of query trees. */static Query *transformRuleStmt(ParseState *pstate, RuleStmt *stmt){	Query	   *qry;	Query	   *action;	List	   *actions;	qry = makeNode(Query);	qry->commandType = CMD_UTILITY;	/*	 * 'instead nothing' rules with a qualification need a query a	 * rangetable so the rewrite handler can add the negated rule	 * qualification to the original query. We create a query with the new	 * command type CMD_NOTHING here that is treated special by the	 * rewrite system.	 */	if (stmt->actions == NIL)	{		Query	   *nothing_qry = makeNode(Query);		nothing_qry->commandType = CMD_NOTHING;		addRangeTableEntry(pstate, stmt->object->relname, "*CURRENT*",						   FALSE, FALSE);		addRangeTableEntry(pstate, stmt->object->relname, "*NEW*",						   FALSE, FALSE);		nothing_qry->rtable = pstate->p_rtable;		stmt->actions = lappend(NIL, nothing_qry);	}	actions = stmt->actions;	/*	 * transform each statment, like parse_analyze()	 */	while (actions != NIL)	{		/*		 * NOTE: 'CURRENT' must always have a varno equal to 1 and 'NEW'		 * equal to 2.		 */		addRangeTableEntry(pstate, stmt->object->relname, "*CURRENT*",						   FALSE, FALSE);		addRangeTableEntry(pstate, stmt->object->relname, "*NEW*",						   FALSE, FALSE);		pstate->p_last_resno = 1;		pstate->p_is_rule = true;		/* for expand all */		pstate->p_hasAggs = false;		action = (Query *) lfirst(actions);		if (action->commandType != CMD_NOTHING)			lfirst(actions) = transformStmt(pstate, lfirst(actions));		actions = lnext(actions);	}	/* take care of the where clause */	stmt->whereClause = transformWhereClause(pstate, stmt->whereClause, NULL);	qry->hasSubLinks = pstate->p_hasSubLinks;	qry->utilityStmt = (Node *) stmt;	return qry;}/* * transformSelectStmt - *	  transforms a Select Statement * */static Query *transformSelectStmt(ParseState *pstate, SelectStmt *stmt){	Query	   *qry = makeNode(Query);	Node	   *qual;	qry->commandType = CMD_SELECT;	/* set up a range table */	makeRangeTable(pstate, NULL, stmt->fromClause, &qual);	qry->uniqueFlag = stmt->unique;	qry->into = stmt->into;	qry->isTemp = stmt->istemp;	qry->isPortal = FALSE;	qry->targetList = transformTargetList(pstate, stmt->targetList);	qry->qual = transformWhereClause(pstate, stmt->whereClause, qual);	/*	 * The havingQual has a similar meaning as "qual" in the where	 * statement. So we can easily use the code from the "where clause"	 * with some additional traversals done in optimizer/plan/planner.c	 */	qry->havingQual = transformWhereClause(pstate, stmt->havingClause, NULL);	qry->hasSubLinks = pstate->p_hasSubLinks;	qry->sortClause = transformSortClause(pstate,										  stmt->sortClause,										  NIL,										  qry->targetList,										  qry->uniqueFlag);	qry->groupClause = transformGroupClause(pstate,											stmt->groupClause,											qry->targetList);	qry->rtable = pstate->p_rtable;	qry->hasAggs = pstate->p_hasAggs;	if (pstate->p_hasAggs || qry->groupClause)		parseCheckAggregates(pstate, qry);	/*	 * The INSERT INTO ... SELECT ... could have a UNION in child, so	 * unionClause may be false	 */	qry->unionall = stmt->unionall;	/***S*I***/	/*	 * Just hand through the unionClause and intersectClause. We will	 * handle it in the function Except_Intersect_Rewrite()	 */	qry->unionClause = stmt->unionClause;	qry->intersectClause = stmt->intersectClause;	/*	 * If there is a havingQual but there are no aggregates, then there is	 * something wrong with the query because having must contain	 * aggregates in its expressions! Otherwise the query could have been	 * formulated using the where clause.	 */	if ((qry->hasAggs == false) && (qry->havingQual != NULL))	{		elog(ERROR, "SELECT/HAVING requires aggregates to be valid");		return (Query *) NIL;	}	if (stmt->forUpdate != NULL)		transformForUpdate(qry, stmt->forUpdate);	return (Query *) qry;}/* * transformUpdateStmt - *	  transforms an update statement * */static Query *transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt){	Query	   *qry = makeNode(Query);	qry->commandType = CMD_UPDATE;	pstate->p_is_update = true;	/*	 * the FROM clause is non-standard SQL syntax. We used to be able to	 * do this with REPLACE in POSTQUEL so we keep the feature.	 */	makeRangeTable(pstate, stmt->relname, stmt->fromClause, NULL);	qry->targetList = transformTargetList(pstate, stmt->targetList);	qry->qual = transformWhereClause(pstate, stmt->whereClause, NULL);	qry->hasSubLinks = pstate->p_hasSubLinks;	qry->rtable = pstate->p_rtable;	qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);	qry->hasAggs = pstate->p_hasAggs;	if (pstate->p_hasAggs)		parseCheckAggregates(pstate, qry);	return (Query *) qry;}/* * transformCursorStmt - *	  transform a Create Cursor Statement * */static Query *transformCursorStmt(ParseState *pstate, SelectStmt *stmt){	Query	   *qry;	qry = transformSelectStmt(pstate, stmt);	qry->into = stmt->portalname;	qry->isTemp = stmt->istemp;	qry->isPortal = TRUE;	qry->isBinary = stmt->binary;		/* internal portal */	return qry;}/***S*I***//* This function steps through the tree * built up by the select_w_o_sort rule * and builds a list of all SelectStmt Nodes found * The built up list is handed back in **select_list. * If one of the SelectStmt Nodes has the 'unionall' flag * set to true *unionall_present hands back 'true' */voidcreate_select_list(Node *ptr, List **select_list, bool *unionall_present){	if (IsA(ptr, SelectStmt))	{		*select_list = lappend(*select_list, ptr);		if (((SelectStmt *) ptr)->unionall == TRUE)			*unionall_present = TRUE;		return;	}	/* Recursively call for all arguments. A NOT expr has no lexpr! */	if (((A_Expr *) ptr)->lexpr != NULL)		create_select_list(((A_Expr *) ptr)->lexpr, select_list, unionall_present);	create_select_list(((A_Expr *) ptr)->rexpr, select_list, unionall_present);}/* Changes the A_Expr Nodes to Expr Nodes and exchanges ANDs and ORs. * The reason for the exchange is easy: We implement INTERSECTs and EXCEPTs * by rewriting these queries to semantically equivalent queries that use * IN and NOT IN subselects. To be able to use all three operations * (UNIONs INTERSECTs and EXCEPTs) in one complex query we have to * translate the queries into Disjunctive Normal Form (DNF). Unfortunately * there is no function 'dnfify' but there is a function 'cnfify' * which produces DNF when we exchange ANDs and ORs before calling * 'cnfify' and exchange them back in the result. * * If an EXCEPT or INTERSECT is present *intersect_present * hands back 'true' */Node *A_Expr_to_Expr(Node *ptr, bool *intersect_present){	Node	   *result = NULL;	switch (nodeTag(ptr))	{		case T_A_Expr:			{				A_Expr	   *a = (A_Expr *) ptr;				switch (a->oper)				{					case AND:						{							Expr	   *expr = makeNode(Expr);							Node	   *lexpr = A_Expr_to_Expr(((A_Expr *) ptr)->lexpr, intersect_present);							Node	   *rexpr = A_Expr_to_Expr(((A_Expr *) ptr)->rexpr, intersect_present);							*intersect_present = TRUE;							expr->typeOid = BOOLOID;							expr->opType = OR_EXPR;							expr->args = makeList(lexpr, rexpr, -1);							result = (Node *) expr;							break;						}					case OR:						{							Expr	   *expr = makeNode(Expr);							Node	   *lexpr = A_Expr_to_Expr(((A_Expr *) ptr)->lexpr, intersect_present);							Node	   *rexpr = A_Expr_to_Expr(((A_Expr *) ptr)->rexpr, intersect_present);							expr->typeOid = BOOLOID;							expr->opType = AND_EXPR;							expr->args = makeList(lexpr, rexpr, -1);							result = (Node *) expr;							break;						}					case NOT:						{							Expr	   *expr = makeNode(Expr);							Node	   *rexpr = A_Expr_to_Expr(((A_Expr *) ptr)->rexpr, intersect_present);							expr->typeOid = BOOLOID;							expr->opType = NOT_EXPR;							expr->args = makeList(rexpr, -1);							result = (Node *) expr;							break;						}				}				break;			}		default:			result = ptr;	}	return result;}voidCheckSelectForUpdate(Query *qry){	if (qry->unionClause != NULL)		elog(ERROR, "SELECT FOR UPDATE is not allowed with UNION/INTERSECT/EXCEPT clause");	if (qry->uniqueFlag != NULL)		elog(ERROR, "SELECT FOR UPDATE is not allowed with DISTINCT clause");	if (qry->groupClause != NULL)		elog(ERROR, "SELECT FOR UPDATE is not allowed with GROUP BY clause");	if (qry->hasAggs)		elog(ERROR, "SELECT FOR UPDATE is not allowed with AGGREGATE");}static voidtransformForUpdate(Query *qry, List *forUpdate){	List	   *rowMark = NULL;	RowMark    *newrm;	List	   *l;	Index		i;	CheckSelectForUpdate(qry);	if (lfirst(forUpdate) == NULL)		/* all tables */	{		i = 1;		foreach(l, qry->rtable)		{			newrm = makeNode(RowMark);			newrm->rti = i++;			newrm->info = ROW_MARK_FOR_UPDATE | ROW_ACL_FOR_UPDATE;			rowMark = lappend(rowMark, newrm);		}		qry->rowMark = nconc(qry->rowMark, rowMark);		return;	}	foreach(l, forUpdate)	{		List	   *l2;		List	   *l3;		i = 1;		foreach(l2, qry->rtable)		{			if (strcmp(((RangeTblEntry *) lfirst(l2))->refname, lfirst(l)) == 0)			{				foreach(l3, rowMark)				{					if (((RowMark *) lfirst(l3))->rti == i)		/* duplicate */						break;				}				if (l3 == NULL)				{					newrm = makeNode(RowMark);					newrm->rti = i;					newrm->info = ROW_MARK_FOR_UPDATE | ROW_ACL_FOR_UPDATE;					rowMark = lappend(rowMark, newrm);				}				break;			}			i++;		}		if (l2 == NULL)			elog(ERROR, "FOR UPDATE: relation %s not found in FROM clause", lfirst(l));	}	qry->rowMark = rowMark;	return;}

⌨️ 快捷键说明

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