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

📄 parse_expr.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 4 页
字号:
				errmsg("improper qualified name (too many dotted names): %s",					   NameListToString(cref->fields))));			node = NULL;		/* keep compiler quiet */			break;	}	return node;}static Node *transformParamRef(ParseState *pstate, ParamRef *pref){	int			paramno = pref->number;	ParseState *toppstate;	Param	   *param;	/*	 * Find topmost ParseState, which is where paramtype info lives.	 */	toppstate = pstate;	while (toppstate->parentParseState != NULL)		toppstate = toppstate->parentParseState;	/* Check parameter number is in range */	if (paramno <= 0)			/* probably can't happen? */		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_PARAMETER),				 errmsg("there is no parameter $%d", paramno)));	if (paramno > toppstate->p_numparams)	{		if (!toppstate->p_variableparams)			ereport(ERROR,					(errcode(ERRCODE_UNDEFINED_PARAMETER),					 errmsg("there is no parameter $%d",							paramno)));		/* Okay to enlarge param array */		if (toppstate->p_paramtypes)			toppstate->p_paramtypes =				(Oid *) repalloc(toppstate->p_paramtypes,								 paramno * sizeof(Oid));		else			toppstate->p_paramtypes =				(Oid *) palloc(paramno * sizeof(Oid));		/* Zero out the previously-unreferenced slots */		MemSet(toppstate->p_paramtypes + toppstate->p_numparams,			   0,			   (paramno - toppstate->p_numparams) * sizeof(Oid));		toppstate->p_numparams = paramno;	}	if (toppstate->p_variableparams)	{		/* If not seen before, initialize to UNKNOWN type */		if (toppstate->p_paramtypes[paramno - 1] == InvalidOid)			toppstate->p_paramtypes[paramno - 1] = UNKNOWNOID;	}	param = makeNode(Param);	param->paramkind = PARAM_NUM;	param->paramid = (AttrNumber) paramno;	param->paramtype = toppstate->p_paramtypes[paramno - 1];	return (Node *) param;}static Node *transformAExprOp(ParseState *pstate, A_Expr *a){	Node	   *lexpr = a->lexpr;	Node	   *rexpr = a->rexpr;	Node	   *result;	/*	 * Special-case "foo = NULL" and "NULL = foo" for compatibility with	 * standards-broken products (like Microsoft's).  Turn these into IS NULL	 * exprs.	 */	if (Transform_null_equals &&		list_length(a->name) == 1 &&		strcmp(strVal(linitial(a->name)), "=") == 0 &&		(exprIsNullConstant(lexpr) || exprIsNullConstant(rexpr)))	{		NullTest   *n = makeNode(NullTest);		n->nulltesttype = IS_NULL;		if (exprIsNullConstant(lexpr))			n->arg = (Expr *) rexpr;		else			n->arg = (Expr *) lexpr;		result = transformExpr(pstate, (Node *) n);	}	else if (lexpr && IsA(lexpr, RowExpr) &&			 rexpr && IsA(rexpr, SubLink) &&			 ((SubLink *) rexpr)->subLinkType == EXPR_SUBLINK)	{		/*		 * Convert "row op subselect" into a MULTIEXPR sublink. Formerly the		 * grammar did this, but now that a row construct is allowed anywhere		 * in expressions, it's easier to do it here.		 */		SubLink    *s = (SubLink *) rexpr;		s->subLinkType = MULTIEXPR_SUBLINK;		s->lefthand = ((RowExpr *) lexpr)->args;		s->operName = a->name;		result = transformExpr(pstate, (Node *) s);	}	else if (lexpr && IsA(lexpr, RowExpr) &&			 rexpr && IsA(rexpr, RowExpr))	{		/* "row op row" */		result = make_row_op(pstate, a->name, lexpr, rexpr);	}	else	{		/* Ordinary scalar operator */		lexpr = transformExpr(pstate, lexpr);		rexpr = transformExpr(pstate, rexpr);		result = (Node *) make_op(pstate,								  a->name,								  lexpr,								  rexpr);	}	return result;}static Node *transformAExprAnd(ParseState *pstate, A_Expr *a){	Node	   *lexpr = transformExpr(pstate, a->lexpr);	Node	   *rexpr = transformExpr(pstate, a->rexpr);	lexpr = coerce_to_boolean(pstate, lexpr, "AND");	rexpr = coerce_to_boolean(pstate, rexpr, "AND");	return (Node *) makeBoolExpr(AND_EXPR,								 list_make2(lexpr, rexpr));}static Node *transformAExprOr(ParseState *pstate, A_Expr *a){	Node	   *lexpr = transformExpr(pstate, a->lexpr);	Node	   *rexpr = transformExpr(pstate, a->rexpr);	lexpr = coerce_to_boolean(pstate, lexpr, "OR");	rexpr = coerce_to_boolean(pstate, rexpr, "OR");	return (Node *) makeBoolExpr(OR_EXPR,								 list_make2(lexpr, rexpr));}static Node *transformAExprNot(ParseState *pstate, A_Expr *a){	Node	   *rexpr = transformExpr(pstate, a->rexpr);	rexpr = coerce_to_boolean(pstate, rexpr, "NOT");	return (Node *) makeBoolExpr(NOT_EXPR,								 list_make1(rexpr));}static Node *transformAExprOpAny(ParseState *pstate, A_Expr *a){	Node	   *lexpr = transformExpr(pstate, a->lexpr);	Node	   *rexpr = transformExpr(pstate, a->rexpr);	return (Node *) make_scalar_array_op(pstate,										 a->name,										 true,										 lexpr,										 rexpr);}static Node *transformAExprOpAll(ParseState *pstate, A_Expr *a){	Node	   *lexpr = transformExpr(pstate, a->lexpr);	Node	   *rexpr = transformExpr(pstate, a->rexpr);	return (Node *) make_scalar_array_op(pstate,										 a->name,										 false,										 lexpr,										 rexpr);}static Node *transformAExprDistinct(ParseState *pstate, A_Expr *a){	Node	   *lexpr = a->lexpr;	Node	   *rexpr = a->rexpr;	if (lexpr && IsA(lexpr, RowExpr) &&		rexpr && IsA(rexpr, RowExpr))	{		/* "row op row" */		return make_row_distinct_op(pstate, a->name,									lexpr, rexpr);	}	else	{		/* Ordinary scalar operator */		lexpr = transformExpr(pstate, lexpr);		rexpr = transformExpr(pstate, rexpr);		return (Node *) make_distinct_op(pstate,										 a->name,										 lexpr,										 rexpr);	}}static Node *transformAExprNullIf(ParseState *pstate, A_Expr *a){	Node	   *lexpr = transformExpr(pstate, a->lexpr);	Node	   *rexpr = transformExpr(pstate, a->rexpr);	Node	   *result;	result = (Node *) make_op(pstate,							  a->name,							  lexpr,							  rexpr);	if (((OpExpr *) result)->opresulttype != BOOLOID)		ereport(ERROR,				(errcode(ERRCODE_DATATYPE_MISMATCH),				 errmsg("NULLIF requires = operator to yield boolean")));	/*	 * We rely on NullIfExpr and OpExpr being the same struct	 */	NodeSetTag(result, T_NullIfExpr);	return result;}static Node *transformAExprOf(ParseState *pstate, A_Expr *a){	/*	 * Checking an expression for match to type.  Will result in a boolean	 * constant node.	 */	ListCell   *telem;	A_Const    *n;	Oid			ltype,				rtype;	bool		matched = false;	Node	   *lexpr = transformExpr(pstate, a->lexpr);	ltype = exprType(lexpr);	foreach(telem, (List *) a->rexpr)	{		rtype = LookupTypeName(lfirst(telem));		matched = (rtype == ltype);		if (matched)			break;	}	/*	 * Expect two forms: equals or not equals.	Flip the sense of the result	 * for not equals.	 */	if (strcmp(strVal(linitial(a->name)), "!=") == 0)		matched = (!matched);	n = makeNode(A_Const);	n->val.type = T_String;	n->val.val.str = (matched ? "t" : "f");	n->typename = SystemTypeName("bool");	return transformExpr(pstate, (Node *) n);}static Node *transformFuncCall(ParseState *pstate, FuncCall *fn){	List	   *targs;	ListCell   *args;	/*	 * Transform the list of arguments.  We use a shallow list copy and then	 * transform-in-place to avoid O(N^2) behavior from repeated lappend's.	 *	 * XXX: repeated lappend() would no longer result in O(n^2) behavior;	 * worth reconsidering this design?	 */	targs = list_copy(fn->args);	foreach(args, targs)	{		lfirst(args) = transformExpr(pstate,									 (Node *) lfirst(args));	}	return ParseFuncOrColumn(pstate,							 fn->funcname,							 targs,							 fn->agg_star,							 fn->agg_distinct,							 false);}static Node *transformCaseExpr(ParseState *pstate, CaseExpr *c){	CaseExpr   *newc;	Node	   *arg;	CaseTestExpr *placeholder;	List	   *newargs;	List	   *typeids;	ListCell   *l;	Node	   *defresult;	Oid			ptype;	/* If we already transformed this node, do nothing */	if (OidIsValid(c->casetype))		return (Node *) c;	newc = makeNode(CaseExpr);	/* transform the test expression, if any */	arg = transformExpr(pstate, (Node *) c->arg);	/* generate placeholder for test expression */	if (arg)	{		/*		 * If test expression is an untyped literal, force it to text. We have		 * to do something now because we won't be able to do this coercion on		 * the placeholder.  This is not as flexible as what was done in 7.4		 * and before, but it's good enough to handle the sort of silly coding		 * commonly seen.		 */		if (exprType(arg) == UNKNOWNOID)			arg = coerce_to_common_type(pstate, arg, TEXTOID, "CASE");		placeholder = makeNode(CaseTestExpr);		placeholder->typeId = exprType(arg);		placeholder->typeMod = exprTypmod(arg);	}	else		placeholder = NULL;	newc->arg = (Expr *) arg;	/* transform the list of arguments */	newargs = NIL;	typeids = NIL;	foreach(l, c->args)	{		CaseWhen   *w = (CaseWhen *) lfirst(l);		CaseWhen   *neww = makeNode(CaseWhen);		Node	   *warg;		Assert(IsA(w, CaseWhen));		warg = (Node *) w->expr;		if (placeholder)		{			/* shorthand form was specified, so expand... */			warg = (Node *) makeSimpleA_Expr(AEXPR_OP, "=",											 (Node *) placeholder,											 warg);		}		neww->expr = (Expr *) transformExpr(pstate, warg);		neww->expr = (Expr *) coerce_to_boolean(pstate,												(Node *) neww->expr,												"CASE/WHEN");		warg = (Node *) w->result;		neww->result = (Expr *) transformExpr(pstate, warg);		newargs = lappend(newargs, neww);		typeids = lappend_oid(typeids, exprType((Node *) neww->result));	}	newc->args = newargs;	/* transform the default clause */	defresult = (Node *) c->defresult;	if (defresult == NULL)	{		A_Const    *n = makeNode(A_Const);		n->val.type = T_Null;		defresult = (Node *) n;	}	newc->defresult = (Expr *) transformExpr(pstate, defresult);	/*	 * Note: default result is considered the most significant type in	 * determining preferred type. This is how the code worked before, but it	 * seems a little bogus to me --- tgl	 */	typeids = lcons_oid(exprType((Node *) newc->defresult), typeids);	ptype = select_common_type(typeids, "CASE");	Assert(OidIsValid(ptype));	newc->casetype = ptype;	/* Convert default result clause, if necessary */	newc->defresult = (Expr *)		coerce_to_common_type(pstate,							  (Node *) newc->defresult,							  ptype,							  "CASE/ELSE");	/* Convert when-clause results, if necessary */	foreach(l, newc->args)	{		CaseWhen   *w = (CaseWhen *) lfirst(l);		w->result = (Expr *)			coerce_to_common_type(pstate,								  (Node *) w->result,								  ptype,								  "CASE/WHEN");	}	return (Node *) newc;}static Node *transformSubLink(ParseState *pstate, SubLink *sublink){	List	   *qtrees;	Query	   *qtree;	Node	   *result = (Node *) sublink;	/* If we already transformed this node, do nothing */	if (IsA(sublink->subselect, Query))		return result;	pstate->p_hasSubLinks = true;	qtrees = parse_sub_analyze(sublink->subselect, pstate);	if (list_length(qtrees) != 1)		elog(ERROR, "bad query in sub-select");	qtree = (Query *) linitial(qtrees);	if (qtree->commandType != CMD_SELECT ||		qtree->resultRelation != 0)		elog(ERROR, "bad query in sub-select");	sublink->subselect = (Node *) qtree;	if (sublink->subLinkType == EXISTS_SUBLINK)	{		/*		 * EXISTS needs no lefthand or combining operator.	These fields		 * should be NIL already, but make sure.		 */		sublink->lefthand = NIL;		sublink->operName = NIL;		sublink->operOids = NIL;		sublink->useOr = FALSE;	}	else if (sublink->subLinkType == EXPR_SUBLINK ||			 sublink->subLinkType == ARRAY_SUBLINK)	{		ListCell   *tlist_item = list_head(qtree->targetList);		/*		 * Make sure the subselect delivers a single column (ignoring resjunk		 * targets).		 */		if (tlist_item == NULL ||			((TargetEntry *) lfirst(tlist_item))->resjunk)			ereport(ERROR,					(errcode(ERRCODE_SYNTAX_ERROR),					 errmsg("subquery must return a column")));		while ((tlist_item = lnext(tlist_item)) != NULL)		{			if (!((TargetEntry *) lfirst(tlist_item))->resjunk)				ereport(ERROR,						(errcode(ERRCODE_SYNTAX_ERROR),						 errmsg("subquery must return only one column")));		}		/*		 * EXPR and ARRAY need no lefthand or combining operator. These fields		 * should be NIL already, but make sure.		 */		sublink->lefthand = NIL;		sublink->operName = NIL;		sublink->operOids = NIL;		sublink->useOr = FALSE;	}	else

⌨️ 快捷键说明

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