diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 1999-08-25 23:21:43 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 1999-08-25 23:21:43 +0000 |
commit | 42af56e1ead3306d2c056ff96ea770e4eee68e9d (patch) | |
tree | 4d2084947e9f546f4104665cf686b05dedee2428 /src/backend/parser/parse_expr.c | |
parent | edda70c0def3f4a4b3bb211cd40f7d169062b95f (diff) | |
download | postgresql-42af56e1ead3306d2c056ff96ea770e4eee68e9d.tar.gz postgresql-42af56e1ead3306d2c056ff96ea770e4eee68e9d.zip |
Revise implementation of SubLinks so that there is a consistent,
documented intepretation of the lefthand and oper fields. Fix a number of
obscure problems while at it --- for example, the old code failed if the parser
decided to insert a type-coercion function just below the operator of a
SubLink.
CAUTION: this will break stored rules that contain subplans. You may
need to initdb.
Diffstat (limited to 'src/backend/parser/parse_expr.c')
-rw-r--r-- | src/backend/parser/parse_expr.c | 66 |
1 files changed, 46 insertions, 20 deletions
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 0ecee29f52d..a2280a74511 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -7,12 +7,14 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.56 1999/08/05 02:33:53 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.57 1999/08/25 23:21:34 tgl Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" + +#include "catalog/pg_operator.h" #include "nodes/makefuncs.h" #include "nodes/params.h" #include "nodes/relation.h" @@ -22,6 +24,7 @@ #include "parser/parse_coerce.h" #include "parser/parse_expr.h" #include "parser/parse_func.h" +#include "parser/parse_oper.h" #include "parser/parse_relation.h" #include "parser/parse_target.h" #include "utils/builtins.h" @@ -209,7 +212,15 @@ transformExpr(ParseState *pstate, Node *expr, int precedence) elog(ERROR, "parser: bad query in subselect"); sublink->subselect = (Node *) qtree; - if (sublink->subLinkType != EXISTS_SUBLINK) + if (sublink->subLinkType == EXISTS_SUBLINK) + { + /* EXISTS needs no lefthand or combining operator. + * These fields should be NIL already, but make sure. + */ + sublink->lefthand = NIL; + sublink->oper = NIL; + } + else { char *op = lfirst(sublink->oper); List *left_list = sublink->lefthand; @@ -236,27 +247,39 @@ transformExpr(ParseState *pstate, Node *expr, int precedence) { TargetEntry *tent = (TargetEntry *) lfirst(right_list); Node *lexpr; - Expr *op_expr; + Operator optup; + Form_pg_operator opform; + Oper *newop; - if (! tent->resdom->resjunk) - { - if (left_list == NIL) - elog(ERROR, "parser: Subselect has too many fields."); - lexpr = lfirst(left_list); - left_list = lnext(left_list); - op_expr = make_op(op, lexpr, tent->expr); - if (op_expr->typeOid != BOOLOID && - sublink->subLinkType != EXPR_SUBLINK) - elog(ERROR, "parser: '%s' must return 'bool' to be used with quantified predicate subquery", op); - sublink->oper = lappend(sublink->oper, op_expr); - } right_list = lnext(right_list); + if (tent->resdom->resjunk) + continue; + + if (left_list == NIL) + elog(ERROR, "parser: Subselect has too many fields."); + lexpr = lfirst(left_list); + left_list = lnext(left_list); + + optup = oper(op, + exprType(lexpr), + exprType(tent->expr), + FALSE); + opform = (Form_pg_operator) GETSTRUCT(optup); + + if (opform->oprresult != BOOLOID && + sublink->subLinkType != EXPR_SUBLINK) + elog(ERROR, "parser: '%s' must return 'bool' to be used with quantified predicate subquery", op); + + newop = makeOper(oprid(optup),/* opno */ + InvalidOid, /* opid */ + opform->oprresult, + 0, + NULL); + sublink->oper = lappend(sublink->oper, newop); } if (left_list != NIL) elog(ERROR, "parser: Subselect has too few fields."); } - else - sublink->oper = NIL; result = (Node *) expr; break; } @@ -565,10 +588,13 @@ exprType(Node *expr) if (sublink->subLinkType == EXPR_SUBLINK) { - /* return the result type of the combining operator */ - Expr *op_expr = (Expr *) lfirst(sublink->oper); + /* return the result type of the combining operator; + * should only be one... + */ + Oper *op = (Oper *) lfirst(sublink->oper); - type = op_expr->typeOid; + Assert(IsA(op, Oper)); + type = op->opresulttype; } else { |