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

📄 parse_expr.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 4 页
字号:
				 * Although the parser does not ever deal with already-planned				 * expression trees, we support SubPlan nodes in this routine				 * for the convenience of ruleutils.c.				 */				SubPlan    *subplan = (SubPlan *) expr;				if (subplan->subLinkType == EXPR_SUBLINK ||					subplan->subLinkType == ARRAY_SUBLINK)				{					/* get the type of the subselect's first target column */					TargetEntry *tent;					tent = (TargetEntry *) linitial(subplan->plan->targetlist);					Assert(IsA(tent, TargetEntry));					Assert(!tent->resjunk);					type = exprType((Node *) tent->expr);					if (subplan->subLinkType == ARRAY_SUBLINK)					{						type = get_array_type(type);						if (!OidIsValid(type))							ereport(ERROR,									(errcode(ERRCODE_UNDEFINED_OBJECT),									 errmsg("could not find array type for data type %s",							format_type_be(exprType((Node *) tent->expr)))));					}				}				else				{					/* for all other subplan types, result is boolean */					type = BOOLOID;				}			}			break;		case T_FieldSelect:			type = ((FieldSelect *) expr)->resulttype;			break;		case T_FieldStore:			type = ((FieldStore *) expr)->resulttype;			break;		case T_RelabelType:			type = ((RelabelType *) expr)->resulttype;			break;		case T_ConvertRowtypeExpr:			type = ((ConvertRowtypeExpr *) expr)->resulttype;			break;		case T_CaseExpr:			type = ((CaseExpr *) expr)->casetype;			break;		case T_CaseWhen:			type = exprType((Node *) ((CaseWhen *) expr)->result);			break;		case T_CaseTestExpr:			type = ((CaseTestExpr *) expr)->typeId;			break;		case T_ArrayExpr:			type = ((ArrayExpr *) expr)->array_typeid;			break;		case T_RowExpr:			type = ((RowExpr *) expr)->row_typeid;			break;		case T_CoalesceExpr:			type = ((CoalesceExpr *) expr)->coalescetype;			break;		case T_MinMaxExpr:			type = ((MinMaxExpr *) expr)->minmaxtype;			break;		case T_NullIfExpr:			type = exprType((Node *) linitial(((NullIfExpr *) expr)->args));			break;		case T_NullTest:			type = BOOLOID;			break;		case T_BooleanTest:			type = BOOLOID;			break;		case T_CoerceToDomain:			type = ((CoerceToDomain *) expr)->resulttype;			break;		case T_CoerceToDomainValue:			type = ((CoerceToDomainValue *) expr)->typeId;			break;		case T_SetToDefault:			type = ((SetToDefault *) expr)->typeId;			break;		default:			elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr));			type = InvalidOid;	/* keep compiler quiet */			break;	}	return type;}/* *	exprTypmod - *	  returns the type-specific attrmod of the expression, if it can be *	  determined.  In most cases, it can't and we return -1. */int32exprTypmod(Node *expr){	if (!expr)		return -1;	switch (nodeTag(expr))	{		case T_Var:			return ((Var *) expr)->vartypmod;		case T_Const:			{				/* Be smart about string constants... */				Const	   *con = (Const *) expr;				switch (con->consttype)				{					case BPCHAROID:						if (!con->constisnull)						{							int32		len = VARSIZE(DatumGetPointer(con->constvalue)) - VARHDRSZ;							/* if multi-byte, take len and find # characters */							if (pg_database_encoding_max_length() > 1)								len = pg_mbstrlen_with_len(VARDATA(DatumGetPointer(con->constvalue)), len);							return len + VARHDRSZ;						}						break;					default:						break;				}			}			break;		case T_FuncExpr:			{				int32		coercedTypmod;				/* Be smart about length-coercion functions... */				if (exprIsLengthCoercion(expr, &coercedTypmod))					return coercedTypmod;			}			break;		case T_FieldSelect:			return ((FieldSelect *) expr)->resulttypmod;		case T_RelabelType:			return ((RelabelType *) expr)->resulttypmod;		case T_CaseExpr:			{				/*				 * If all the alternatives agree on type/typmod, return that				 * typmod, else use -1				 */				CaseExpr   *cexpr = (CaseExpr *) expr;				Oid			casetype = cexpr->casetype;				int32		typmod;				ListCell   *arg;				if (!cexpr->defresult)					return -1;				if (exprType((Node *) cexpr->defresult) != casetype)					return -1;				typmod = exprTypmod((Node *) cexpr->defresult);				if (typmod < 0)					return -1;	/* no point in trying harder */				foreach(arg, cexpr->args)				{					CaseWhen   *w = (CaseWhen *) lfirst(arg);					Assert(IsA(w, CaseWhen));					if (exprType((Node *) w->result) != casetype)						return -1;					if (exprTypmod((Node *) w->result) != typmod)						return -1;				}				return typmod;			}			break;		case T_CaseTestExpr:			return ((CaseTestExpr *) expr)->typeMod;		case T_CoalesceExpr:			{				/*				 * If all the alternatives agree on type/typmod, return that				 * typmod, else use -1				 */				CoalesceExpr *cexpr = (CoalesceExpr *) expr;				Oid			coalescetype = cexpr->coalescetype;				int32		typmod;				ListCell   *arg;				if (exprType((Node *) linitial(cexpr->args)) != coalescetype)					return -1;				typmod = exprTypmod((Node *) linitial(cexpr->args));				if (typmod < 0)					return -1;	/* no point in trying harder */				for_each_cell(arg, lnext(list_head(cexpr->args)))				{					Node	   *e = (Node *) lfirst(arg);					if (exprType(e) != coalescetype)						return -1;					if (exprTypmod(e) != typmod)						return -1;				}				return typmod;			}			break;		case T_MinMaxExpr:			{				/*				 * If all the alternatives agree on type/typmod, return that				 * typmod, else use -1				 */				MinMaxExpr *mexpr = (MinMaxExpr *) expr;				Oid			minmaxtype = mexpr->minmaxtype;				int32		typmod;				ListCell   *arg;				if (exprType((Node *) linitial(mexpr->args)) != minmaxtype)					return -1;				typmod = exprTypmod((Node *) linitial(mexpr->args));				if (typmod < 0)					return -1;	/* no point in trying harder */				for_each_cell(arg, lnext(list_head(mexpr->args)))				{					Node	   *e = (Node *) lfirst(arg);					if (exprType(e) != minmaxtype)						return -1;					if (exprTypmod(e) != typmod)						return -1;				}				return typmod;			}			break;		case T_NullIfExpr:			{				NullIfExpr *nexpr = (NullIfExpr *) expr;				return exprTypmod((Node *) linitial(nexpr->args));			}			break;		case T_CoerceToDomain:			return ((CoerceToDomain *) expr)->resulttypmod;		case T_CoerceToDomainValue:			return ((CoerceToDomainValue *) expr)->typeMod;		case T_SetToDefault:			return ((SetToDefault *) expr)->typeMod;		default:			break;	}	return -1;}/* * exprIsLengthCoercion *		Detect whether an expression tree is an application of a datatype's *		typmod-coercion function.  Optionally extract the result's typmod. * * If coercedTypmod is not NULL, the typmod is stored there if the expression * is a length-coercion function, else -1 is stored there. * * Note that a combined type-and-length coercion will be treated as a * length coercion by this routine. */boolexprIsLengthCoercion(Node *expr, int32 *coercedTypmod){	FuncExpr   *func;	int			nargs;	Const	   *second_arg;	if (coercedTypmod != NULL)		*coercedTypmod = -1;	/* default result on failure */	/* Is it a function-call at all? */	if (expr == NULL || !IsA(expr, FuncExpr))		return false;	func = (FuncExpr *) expr;	/*	 * If it didn't come from a coercion context, reject.	 */	if (func->funcformat != COERCE_EXPLICIT_CAST &&		func->funcformat != COERCE_IMPLICIT_CAST)		return false;	/*	 * If it's not a two-argument or three-argument function with the second	 * argument being an int4 constant, it can't have been created from a	 * length coercion (it must be a type coercion, instead).	 */	nargs = list_length(func->args);	if (nargs < 2 || nargs > 3)		return false;	second_arg = (Const *) lsecond(func->args);	if (!IsA(second_arg, Const) ||		second_arg->consttype != INT4OID ||		second_arg->constisnull)		return false;	/*	 * OK, it is indeed a length-coercion function.	 */	if (coercedTypmod != NULL)		*coercedTypmod = DatumGetInt32(second_arg->constvalue);	return true;}/* * Handle an explicit CAST construct. * * The given expr has already been transformed, but we need to lookup * the type name and then apply any necessary coercion function(s). */static Node *typecast_expression(ParseState *pstate, Node *expr, TypeName *typename){	Oid			inputType = exprType(expr);	Oid			targetType;	targetType = typenameTypeId(typename);	if (inputType == InvalidOid)		return expr;			/* do nothing if NULL input */	expr = coerce_to_target_type(pstate, expr, inputType,								 targetType, typename->typmod,								 COERCION_EXPLICIT,								 COERCE_EXPLICIT_CAST);	if (expr == NULL)		ereport(ERROR,				(errcode(ERRCODE_CANNOT_COERCE),				 errmsg("cannot cast type %s to %s",						format_type_be(inputType),						format_type_be(targetType))));	return expr;}/* * Transform a "row op row" construct */static Node *make_row_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree){	Node	   *result = NULL;	RowExpr    *lrow,			   *rrow;	List	   *largs,			   *rargs;	ListCell   *l,			   *r;	char	   *oprname;	BoolExprType boolop;	/* Inputs are untransformed RowExprs */	lrow = (RowExpr *) transformExpr(pstate, ltree);	rrow = (RowExpr *) transformExpr(pstate, rtree);	Assert(IsA(lrow, RowExpr));	Assert(IsA(rrow, RowExpr));	largs = lrow->args;	rargs = rrow->args;	if (list_length(largs) != list_length(rargs))		ereport(ERROR,				(errcode(ERRCODE_SYNTAX_ERROR),				 errmsg("unequal number of entries in row expression")));	/*	 * XXX it's really wrong to generate a simple AND combination for < <= >	 * >=.	We probably need to invent a new runtime node type to handle those	 * correctly.  For the moment, though, keep on doing this ...	 */	oprname = strVal(llast(opname));	if ((strcmp(oprname, "=") == 0) ||		(strcmp(oprname, "<") == 0) ||		(strcmp(oprname, "<=") == 0) ||		(strcmp(oprname, ">") == 0) ||		(strcmp(oprname, ">=") == 0))		boolop = AND_EXPR;	else if (strcmp(oprname, "<>") == 0)		boolop = OR_EXPR;	else	{		ereport(ERROR,				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),				 errmsg("operator %s is not supported for row expressions",						oprname)));		boolop = 0;				/* keep compiler quiet */	}	forboth(l, largs, r, rargs)	{		Node	   *larg = (Node *) lfirst(l);		Node	   *rarg = (Node *) lfirst(r);		Node	   *cmp;		cmp = (Node *) make_op(pstate, opname, larg, rarg);		cmp = coerce_to_boolean(pstate, cmp, "row comparison");		if (result == NULL)			result = cmp;		else			result = (Node *) makeBoolExpr(boolop,										   list_make2(result, cmp));	}	if (result == NULL)	{		/* zero-length rows?  Generate constant TRUE or FALSE */		if (boolop == AND_EXPR)			result = makeBoolConst(true, false);		else			result = makeBoolConst(false, false);	}	return result;}/* * Transform a "row IS DISTINCT FROM row" construct */static Node *make_row_distinct_op(ParseState *pstate, List *opname,					 Node *ltree, Node *rtree){	Node	   *result = NULL;	RowExpr    *lrow,			   *rrow;	List	   *largs,			   *rargs;	ListCell   *l,			   *r;	/* Inputs are untransformed RowExprs */	lrow = (RowExpr *) transformExpr(pstate, ltree);	rrow = (RowExpr *) transformExpr(pstate, rtree);	Assert(IsA(lrow, RowExpr));	Assert(IsA(rrow, RowExpr));	largs = lrow->args;	rargs = rrow->args;	if (list_length(largs) != list_length(rargs))		ereport(ERROR,				(errcode(ERRCODE_SYNTAX_ERROR),				 errmsg("unequal number of entries in row expression")));	forboth(l, largs, r, rargs)	{		Node	   *larg = (Node *) lfirst(l);		Node	   *rarg = (Node *) lfirst(r);		Node	   *cmp;		cmp = (Node *) make_distinct_op(pstate, opname, larg, rarg);		if (result == NULL)			result = cmp;		else			result = (Node *) makeBoolExpr(OR_EXPR,										   list_make2(result, cmp));	}	if (result == NULL)	{		/* zero-length rows?  Generate constant FALSE */		result = makeBoolConst(false, false);	}	return result;}/* * make the node for an IS DISTINCT FROM operator */static Expr *make_distinct_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree){	Expr	   *result;	result = make_op(pstate, opname, ltree, rtree);	if (((OpExpr *) result)->opresulttype != BOOLOID)		ereport(ERROR,				(errcode(ERRCODE_DATATYPE_MISMATCH),		   errmsg("IS DISTINCT FROM requires = operator to yield boolean")));	/*	 * We rely on DistinctExpr and OpExpr being same struct	 */	NodeSetTag(result, T_DistinctExpr);	return result;}

⌨️ 快捷键说明

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