1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-13 07:41:39 +03:00

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.
This commit is contained in:
Tom Lane
1999-08-25 23:21:43 +00:00
parent edda70c0de
commit 42af56e1ea
8 changed files with 326 additions and 322 deletions

View File

@ -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
{