📄 parse_expr.c
字号:
*/ 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 + -