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

📄 parse_expr.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 2 页
字号:
						 */						c->casetype = ptype;					}					else if (can_coerce_type(1, &c->casetype, &ptype))					{						c->defresult = coerce_type(pstate, c->defresult,												 c->casetype, ptype, -1);						c->casetype = ptype;					}					else					{						elog(ERROR, "CASE/ELSE unable to convert to type %s",							 typeidTypeName(ptype));					}				}				/* Convert when clauses, if not null and if necessary */				foreach(args, c->args)				{					Oid			wtype;					w = lfirst(args);					wtype = exprType(w->result);					/*					 * only bother with conversion if not NULL and					 * different type...					 */					if (wtype && (wtype != UNKNOWNOID)						&& (wtype != ptype))					{						if (can_coerce_type(1, &wtype, &ptype))						{							w->result = coerce_type(pstate, w->result, wtype,													ptype, -1);						}						else						{							elog(ERROR, "CASE/WHEN unable to convert to type %s",								 typeidTypeName(ptype));						}					}				}				result = expr;				break;			}		case T_CaseWhen:			{				CaseWhen   *w = (CaseWhen *) expr;				w->expr = transformExpr(pstate, (Node *) w->expr, precedence);				if (exprType(w->expr) != BOOLOID)					elog(ERROR, "WHEN clause must have a boolean result");				/*				 * result is NULL for NULLIF() construct - thomas				 * 1998-11-11				 */				if (w->result == NULL)				{					A_Const    *n = makeNode(A_Const);					n->val.type = T_Null;					w->result = (Node *) n;				}				w->result = transformExpr(pstate, (Node *) w->result, precedence);				result = expr;				break;			}/* Some nodes do _not_ come from the original parse tree, *	but result from parser transformation in this phase. * At least one construct (BETWEEN/AND) puts the same nodes *	into two branches of the parse tree; hence, some nodes *	are transformed twice. * Another way it can happen is that coercion of an operator or *	function argument to the required type (via coerce_type()) *	can apply transformExpr to an already-transformed subexpression. *	An example here is "SELECT count(*) + 1.0 FROM table". * Thus, we can see node types in this routine that do not appear in the *	original parse tree.  Assume they are already transformed, and just *	pass them through. * Do any other node types need to be accepted?  For now we are taking *	a conservative approach, and only accepting node types that are *	demonstrably necessary to accept. */		case T_Expr:		case T_Var:		case T_Const:		case T_Param:		case T_Aggref:		case T_ArrayRef:			{				result = (Node *) expr;				break;			}		default:			/* should not reach here */			elog(ERROR, "transformExpr: does not know how to transform node %d",				 nodeTag(expr));			break;	}	return result;}static Node *transformIdent(ParseState *pstate, Node *expr, int precedence){	Ident	   *ident = (Ident *) expr;	RangeTblEntry *rte;	Node	   *column_result,			   *relation_result,			   *result;	column_result = relation_result = result = 0;	/* try to find the ident as a column */	if ((rte = colnameRangeTableEntry(pstate, ident->name)) != NULL)	{		Attr	   *att = makeNode(Attr);		/* we add the relation name for them */		att->relname = rte->refname;		att->attrs = lcons(makeString(ident->name), NIL);		column_result = (Node *) ParseNestedFuncOrColumn(pstate, att,									  &pstate->p_last_resno, precedence);	}	/* try to find the ident as a relation */	if (refnameRangeTableEntry(pstate, ident->name) != NULL)	{		ident->isRel = TRUE;		relation_result = (Node *) ident;	}	/* choose the right result based on the precedence */	if (precedence == EXPR_COLUMN_FIRST)	{		if (column_result)			result = column_result;		else			result = relation_result;	}	else	{		if (relation_result)			result = relation_result;		else			result = column_result;	}	if (result == NULL)		elog(ERROR, "attribute '%s' not found", ident->name);	return result;}/* *	exprType - *	  returns the Oid of the type of the expression. (Used for typechecking.) */OidexprType(Node *expr){	Oid			type = (Oid) 0;	if (!expr)		return type;	switch (nodeTag(expr))	{		case T_Func:			type = ((Func *) expr)->functype;			break;		case T_Iter:			type = ((Iter *) expr)->itertype;			break;		case T_Var:			type = ((Var *) expr)->vartype;			break;		case T_Expr:			type = ((Expr *) expr)->typeOid;			break;		case T_Const:			type = ((Const *) expr)->consttype;			break;		case T_ArrayRef:			type = ((ArrayRef *) expr)->refelemtype;			break;		case T_Aggref:			type = ((Aggref *) expr)->aggtype;			break;		case T_Param:			type = ((Param *) expr)->paramtype;			break;		case T_SubLink:			{				SubLink    *sublink = (SubLink *) expr;				if (sublink->subLinkType == EXPR_SUBLINK)				{					/* return the result type of the combining operator */					Expr	   *op_expr = (Expr *) lfirst(sublink->oper);					type = op_expr->typeOid;				}				else				{					/* for all other sublink types, result is boolean */					type = BOOLOID;				}			}			break;		case T_CaseExpr:			type = ((CaseExpr *) expr)->casetype;			break;		case T_CaseWhen:			type = exprType(((CaseWhen *) expr)->result);			break;		case T_Ident:			/* is this right? */			type = UNKNOWNOID;			break;		default:			elog(ERROR, "exprType: don't know how to get type for %d node",				 nodeTag(expr));			break;	}	return type;}static Node *parser_typecast(Value *expr, TypeName *typename, int32 atttypmod){	/* check for passing non-ints */	Const	   *adt;	Datum		lcp;	Type		tp;	char		type_string[NAMEDATALEN];	int32		len;	char	   *cp = NULL;	char	   *const_string = NULL;	bool		string_palloced = false;	switch (nodeTag(expr))	{		case T_String:			const_string = DatumGetPointer(expr->val.str);			break;		case T_Integer:			string_palloced = true;			const_string = int4out(expr->val.ival);			break;		case T_Float:			string_palloced = true;			const_string = float8out(&expr->val.dval);			break;		default:			elog(ERROR,			 "parser_typecast: cannot cast this expression to type '%s'",				 typename->name);	}	if (typename->arrayBounds != NIL)	{		sprintf(type_string, "_%s", typename->name);		tp = (Type) typenameType(type_string);	}	else		tp = (Type) typenameType(typename->name);	len = typeLen(tp);	cp = stringTypeString(tp, const_string, atttypmod);	if (!typeByVal(tp))		lcp = PointerGetDatum(cp);	else	{		switch (len)		{			case 1:				lcp = Int8GetDatum(cp);				break;			case 2:				lcp = Int16GetDatum(cp);				break;			case 4:				lcp = Int32GetDatum(cp);				break;			default:				lcp = PointerGetDatum(cp);				break;		}	}	adt = makeConst(typeTypeId(tp),					len,					(Datum) lcp,					false,					typeByVal(tp),					false,		/* not a set */					true /* is cast */ );	if (string_palloced)		pfree(const_string);	return (Node *) adt;}/* parser_typecast2() * Convert (only) constants to specified type. */Node *parser_typecast2(Node *expr, Oid exprType, Type tp, int32 atttypmod){	/* check for passing non-ints */	Const	   *adt;	Datum		lcp;	int32		len = typeLen(tp);	char	   *cp = NULL;	char	   *const_string = NULL;	bool		string_palloced = false;	Assert(IsA(expr, Const));	switch (exprType)	{		case 0:			/* NULL */			break;		case INT4OID:			/* int4 */			const_string = (char *) palloc(256);			string_palloced = true;			sprintf(const_string, "%d",					(int) ((Const *) expr)->constvalue);			break;		case NAMEOID:			/* name */			const_string = (char *) palloc(256);			string_palloced = true;			sprintf(const_string, "%s",					(char *) ((Const *) expr)->constvalue);			break;		case CHAROID:			/* char */			const_string = (char *) palloc(256);			string_palloced = true;			sprintf(const_string, "%c",					(char) ((Const *) expr)->constvalue);			break;		case FLOAT4OID: /* float4 */			{				float32		floatVal = DatumGetFloat32(((Const *) expr)->constvalue);				const_string = (char *) palloc(256);				string_palloced = true;				sprintf(const_string, "%f", *floatVal);				break;			}		case FLOAT8OID: /* float8 */			{				float64		floatVal = DatumGetFloat64(((Const *) expr)->constvalue);				const_string = (char *) palloc(256);				string_palloced = true;				sprintf(const_string, "%f", *floatVal);				break;			}		case CASHOID:			/* money */			const_string = (char *) palloc(256);			string_palloced = true;			sprintf(const_string, "%ld",					(long) ((Const *) expr)->constvalue);			break;		case TEXTOID:			/* text */			const_string = DatumGetPointer(((Const *) expr)->constvalue);			const_string = (char *) textout((struct varlena *) const_string);			break;		case UNKNOWNOID:		/* unknown */			const_string = DatumGetPointer(((Const *) expr)->constvalue);			const_string = (char *) textout((struct varlena *) const_string);			break;		default:			elog(ERROR, "unknown type %u", exprType);	}	if (!exprType)	{		adt = makeConst(typeTypeId(tp),						(Size) 0,						(Datum) NULL,						true,	/* isnull */						false,	/* was omitted */						false,	/* not a set */						true /* is cast */ );		return (Node *) adt;	}	cp = stringTypeString(tp, const_string, atttypmod);	if (!typeByVal(tp))		lcp = PointerGetDatum(cp);	else	{		switch (len)		{			case 1:				lcp = Int8GetDatum(cp);				break;			case 2:				lcp = Int16GetDatum(cp);				break;			case 4:				lcp = Int32GetDatum(cp);				break;			default:				lcp = PointerGetDatum(cp);				break;		}	}	adt = makeConst(typeTypeId(tp),					(Size) len,					(Datum) lcp,					false,					typeByVal(tp),					false,		/* not a set */					true /* is cast */ );	/*	 * printf("adt %s : %u %d %d\n",CString(expr),typeTypeId(tp) ,	 * len,cp);	 */	if (string_palloced)		pfree(const_string);	return (Node *) adt;}

⌨️ 快捷键说明

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