Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita58843b

Browse files
committed
Fix problems seen when result of a subselect was used in an
expression context (ie, not at the top level of a WHERE clause). Exampleslike this one work now:SELECT name, value FROM t1 as touter WHERE(value/(SELECT AVG(value) FROM t1 WHERE name = touter.name)) > 0.75;
1 parent4438b70 commita58843b

File tree

2 files changed

+57
-23
lines changed

2 files changed

+57
-23
lines changed

‎src/backend/executor/nodeSubplan.c

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,11 @@ ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext)
2929
{
3030
Plan*plan=node->plan;
3131
SubLink*sublink=node->sublink;
32+
SubLinkTypesubLinkType=sublink->subLinkType;
3233
TupleTableSlot*slot;
3334
List*lst;
34-
boolresult= false;
35-
boolfound= false;
35+
Datumresult= (Datum) false;
36+
boolfound= false;/* TRUE if got at least one subplan tuple */
3637

3738
if (node->setParam!=NULL)
3839
elog(ERROR,"ExecSubPlan: can't set parent params from subquery");
@@ -56,6 +57,18 @@ ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext)
5657

5758
ExecReScan(plan, (ExprContext*)NULL,plan);
5859

60+
/*
61+
* For all sublink types except EXPR_SUBLINK, the result type is boolean,
62+
* and we have a fairly clear idea of how to combine multiple subitems
63+
* and deal with NULL values or an empty subplan result.
64+
*
65+
* For EXPR_SUBLINK, the result type is whatever the combining operator
66+
* returns. We have no way to deal with more than one column in the
67+
* subplan result --- hopefully the parser forbids that. More seriously,
68+
* it's unclear what to do with NULL values or an empty subplan result.
69+
* For now, we error out, but should something else happen?
70+
*/
71+
5972
for (slot=ExecProcNode(plan,plan);
6073
!TupIsNull(slot);
6174
slot=ExecProcNode(plan,plan))
@@ -64,13 +77,13 @@ ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext)
6477
TupleDesctdesc=slot->ttc_tupleDescriptor;
6578
inti=1;
6679

67-
if (sublink->subLinkType==EXPR_SUBLINK&&found)
80+
if (subLinkType==EXPR_SUBLINK&&found)
6881
{
6982
elog(ERROR,"ExecSubPlan: more than one tuple returned by expression subselect");
7083
return (Datum) false;
7184
}
7285

73-
if (sublink->subLinkType==EXISTS_SUBLINK)
86+
if (subLinkType==EXISTS_SUBLINK)
7487
return (Datum) true;
7588

7689
found= true;
@@ -82,23 +95,39 @@ ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext)
8295
boolisnull;
8396

8497
con->constvalue=heap_getattr(tup,i,tdesc,&(con->constisnull));
85-
result=(bool)ExecEvalExpr((Node*)expr,econtext,&isnull, (bool*)NULL);
98+
result=ExecEvalExpr((Node*)expr,econtext,&isnull, (bool*)NULL);
8699
if (isnull)
87-
result= false;
88-
if ((!result&& !(sublink->useor))|| (result&&sublink->useor))
89-
break;
100+
{
101+
if (subLinkType==EXPR_SUBLINK)
102+
elog(ERROR,"ExecSubPlan: null value returned by expression subselect");
103+
else
104+
result= (Datum) false;
105+
}
106+
if (subLinkType!=EXPR_SUBLINK)
107+
{
108+
if ((! (bool)result&& !(sublink->useor))||
109+
((bool)result&&sublink->useor))
110+
break;
111+
}
90112
i++;
91113
}
92114

93-
if ((!result&&sublink->subLinkType==ALL_SUBLINK)||
94-
(result&&sublink->subLinkType==ANY_SUBLINK))
115+
if (subLinkType==ALL_SUBLINK&& ! (bool)result)
116+
break;
117+
if (subLinkType==ANY_SUBLINK&& (bool)result)
95118
break;
96119
}
97120

98-
if (!found&&sublink->subLinkType==ALL_SUBLINK)
99-
return (Datum) true;
121+
if (!found)
122+
{
123+
/* deal with empty subplan result. Note default result is 'false' */
124+
if (subLinkType==ALL_SUBLINK)
125+
result= (Datum) true;
126+
elseif (subLinkType==EXPR_SUBLINK)
127+
elog(ERROR,"ExecSubPlan: no tuples returned by expression subselect");
128+
}
100129

101-
return(Datum)result;
130+
returnresult;
102131
}
103132

104133
/* ----------------------------------------------------------------

‎src/backend/parser/parse_expr.c

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.41 1999/04/1817:35:51 tgl Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.42 1999/04/19 04:17:11 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -312,14 +312,6 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
312312

313313
op_expr=make_op(op,lexpr,tent->expr);
314314

315-
/*
316-
* HACK! Second IF is more valid but currently we
317-
* don't support EXPR subqueries inside
318-
* expressions generally, only in WHERE clauses.
319-
* After fixing this, first IF must be removed.
320-
*/
321-
if (op_expr->typeOid!=BOOLOID)
322-
elog(ERROR,"parser: '%s' must return 'bool' to be used with subquery",op);
323315
if (op_expr->typeOid!=BOOLOID&&
324316
sublink->subLinkType!=EXPR_SUBLINK)
325317
elog(ERROR,"parser: '%s' must return 'bool' to be used with quantified predicate subquery",op);
@@ -598,7 +590,20 @@ exprType(Node *expr)
598590
type= ((Param*)expr)->paramtype;
599591
break;
600592
caseT_SubLink:
601-
type=BOOLOID;
593+
{
594+
SubLink*sublink= (SubLink*)expr;
595+
if (sublink->subLinkType==EXPR_SUBLINK)
596+
{
597+
/* return the result type of the combining operator */
598+
Expr*op_expr= (Expr*)lfirst(sublink->oper);
599+
type=op_expr->typeOid;
600+
}
601+
else
602+
{
603+
/* for all other sublink types, result is boolean */
604+
type=BOOLOID;
605+
}
606+
}
602607
break;
603608
caseT_CaseExpr:
604609
type= ((CaseExpr*)expr)->casetype;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp