/* * make_op() * Operator expression construction. * * Transform operator expression ensuring type compatibility. * This is where some type conversion happens. * * As with coerce_type, pstate may be NULL if no special unknown-Param * processing is wanted. */ Expr * make_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree, int location) { Oid ltypeId, rtypeId; Operator tup; Expr *result; /* Select the operator */ if (rtree == NULL) { /* right operator */ ltypeId = exprType(ltree); rtypeId = InvalidOid; tup = right_oper(pstate, opname, ltypeId, false, location); } else if (ltree == NULL) { /* left operator */ rtypeId = exprType(rtree); ltypeId = InvalidOid; tup = left_oper(pstate, opname, rtypeId, false, location); } else { /* otherwise, binary operator */ ltypeId = exprType(ltree); rtypeId = exprType(rtree); tup = oper(pstate, opname, ltypeId, rtypeId, false, location); } /* Do typecasting and build the expression tree */ result = make_op_expr(pstate, tup, ltree, rtree, ltypeId, rtypeId); ReleaseSysCache(tup); return result; }
/* * make_op() * Operator expression construction. * * Transform operator expression ensuring type compatibility. * This is where some type conversion happens. * * As with coerce_type, pstate may be NULL if no special unknown-Param * processing is wanted. */ Expr * make_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree, int location) { Oid ltypeId, rtypeId; Operator tup; Form_pg_operator opform; Oid actual_arg_types[2]; Oid declared_arg_types[2]; int nargs; List *args; Oid rettype; OpExpr *result; /* Select the operator */ if (rtree == NULL) { /* right operator */ ltypeId = exprType(ltree); rtypeId = InvalidOid; tup = right_oper(pstate, opname, ltypeId, false, location); } else if (ltree == NULL) { /* left operator */ rtypeId = exprType(rtree); ltypeId = InvalidOid; tup = left_oper(pstate, opname, rtypeId, false, location); } else { /* otherwise, binary operator */ ltypeId = exprType(ltree); rtypeId = exprType(rtree); tup = oper(pstate, opname, ltypeId, rtypeId, false, location); } opform = (Form_pg_operator) GETSTRUCT(tup); /* Check it's not a shell */ if (!RegProcedureIsValid(opform->oprcode)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_FUNCTION), errmsg("operator is only a shell: %s", op_signature_string(opname, opform->oprkind, opform->oprleft, opform->oprright)), parser_errposition(pstate, location))); /* Do typecasting and build the expression tree */ if (rtree == NULL) { /* right operator */ args = list_make1(ltree); actual_arg_types[0] = ltypeId; declared_arg_types[0] = opform->oprleft; nargs = 1; } else if (ltree == NULL) { /* left operator */ args = list_make1(rtree); actual_arg_types[0] = rtypeId; declared_arg_types[0] = opform->oprright; nargs = 1; } else { /* otherwise, binary operator */ args = list_make2(ltree, rtree); actual_arg_types[0] = ltypeId; actual_arg_types[1] = rtypeId; declared_arg_types[0] = opform->oprleft; declared_arg_types[1] = opform->oprright; nargs = 2; } /* * enforce consistency with polymorphic argument and return types, * possibly adjusting return type or declared_arg_types (which will be * used as the cast destination by make_fn_arguments) */ rettype = enforce_generic_type_consistency(actual_arg_types, declared_arg_types, nargs, opform->oprresult, false); /* perform the necessary typecasting of arguments */ make_fn_arguments(pstate, args, actual_arg_types, declared_arg_types); /* and build the expression node */ result = makeNode(OpExpr); result->opno = oprid(tup); result->opfuncid = opform->oprcode; result->opresulttype = rettype; result->opretset = get_func_retset(opform->oprcode); /* opcollid and inputcollid will be set by parse_collate.c */ result->args = args; result->location = location; ReleaseSysCache(tup); return (Expr *) result; }