aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_oper.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser/parse_oper.c')
-rw-r--r--src/backend/parser/parse_oper.c160
1 files changed, 81 insertions, 79 deletions
diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c
index 6b23fbb9e9a..54fb63f959d 100644
--- a/src/backend/parser/parse_oper.c
+++ b/src/backend/parser/parse_oper.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/parse_oper.c,v 1.101 2008/01/11 18:39:41 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_oper.c,v 1.102 2008/04/22 01:34:34 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -75,9 +75,6 @@ static const char *op_signature_string(List *op, char oprkind,
static void op_error(ParseState *pstate, List *op, char oprkind,
Oid arg1, Oid arg2,
FuncDetailCode fdresult, int location);
-static Expr *make_op_expr(ParseState *pstate, Operator op,
- Node *ltree, Node *rtree,
- Oid ltypeId, Oid rtypeId);
static bool make_oper_cache_key(OprCacheKey *key, List *opname,
Oid ltypeId, Oid rtypeId);
static Oid find_oper_cache_entry(OprCacheKey *key);
@@ -913,7 +910,13 @@ make_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree,
Oid ltypeId,
rtypeId;
Operator tup;
- Expr *result;
+ 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)
@@ -938,12 +941,72 @@ make_op(ParseState *pstate, List *opname, Node *ltree, Node *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 */
- result = make_op_expr(pstate, tup, ltree, rtree, ltypeId, rtypeId);
+ 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);
+ result->args = args;
ReleaseSysCache(tup);
- return result;
+ return (Expr *) result;
}
/*
@@ -992,6 +1055,17 @@ make_scalar_array_op(ParseState *pstate, List *opname,
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)));
+
args = list_make2(ltree, rtree);
actual_arg_types[0] = ltypeId;
actual_arg_types[1] = rtypeId;
@@ -1062,78 +1136,6 @@ make_scalar_array_op(ParseState *pstate, List *opname,
return (Expr *) result;
}
-/*
- * make_op_expr()
- * Build operator expression using an already-looked-up operator.
- *
- * As with coerce_type, pstate may be NULL if no special unknown-Param
- * processing is wanted.
- */
-static Expr *
-make_op_expr(ParseState *pstate, Operator op,
- Node *ltree, Node *rtree,
- Oid ltypeId, Oid rtypeId)
-{
- Form_pg_operator opform = (Form_pg_operator) GETSTRUCT(op);
- Oid actual_arg_types[2];
- Oid declared_arg_types[2];
- int nargs;
- List *args;
- Oid rettype;
- OpExpr *result;
-
- 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(op);
- result->opfuncid = opform->oprcode;
- result->opresulttype = rettype;
- result->opretset = get_func_retset(opform->oprcode);
- result->args = args;
-
- return (Expr *) result;
-}
-
/*
* Lookaside cache to speed operator lookup. Possibly this should be in