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

Commitf68e11f

Browse files
committed
Implement subselects in target lists. Also, relax requirement that
subselects can only appear on the righthand side of a binary operator.That's still true for quantified predicates like x = ANY (SELECT ...),but a subselect that delivers a single result can now appear anywherein an expression. This is implemented by changing EXPR_SUBLINK sublinksto represent just the (SELECT ...) expression, without any 'left handside' or combining operator --- so they're now more like EXISTS_SUBLINK.To handle the case of '(x, y, z) = (SELECT ...)', I added a new sublinktype MULTIEXPR_SUBLINK, which acts just like EXPR_SUBLINK used to.But the grammar will only generate one for a multiple-left-hand-siderow expression.
1 parent1ecb129 commitf68e11f

File tree

12 files changed

+355
-557
lines changed

12 files changed

+355
-557
lines changed

‎src/backend/executor/nodeSubplan.c

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33
* nodeSubplan.c
44
* routines to support subselects
55
*
6+
* Copyright (c) 1994, Regents of the University of California
7+
*
8+
* IDENTIFICATION
9+
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.16 1999/11/15 02:00:01 tgl Exp $
10+
*
611
*-------------------------------------------------------------------------
712
*/
813
/*
@@ -68,19 +73,17 @@ ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext, bool *isNull)
6873
* within a tuple (if there are multiple columns) using OR semantics
6974
* if "useor" is true, AND semantics if not. We then combine results
7075
* across tuples (if the subplan produces more than one) using OR
71-
* semantics for ANY_SUBLINK or AND semantics for ALL_SUBLINK. NULL
72-
* results from the combining operators are handled according to the
73-
* usual SQL semantics for OR and AND. The result for no input
74-
* tuples is FALSE for ANY_SUBLINK, TRUE for ALL_SUBLINK.
76+
* semantics for ANY_SUBLINK or AND semantics for ALL_SUBLINK.
77+
* (MULTIEXPR_SUBLINK doesn't allow multiple tuples from the subplan.)
78+
* NULL results from the combining operators are handled according to
79+
* the usual SQL semantics for OR and AND. The result for no input
80+
* tuples is FALSE for ANY_SUBLINK, TRUE for ALL_SUBLINK, NULL for
81+
* MULTIEXPR_SUBLINK.
7582
*
7683
* For EXPR_SUBLINK we require the subplan to produce no more than one
7784
* tuple, else an error is raised. If zero tuples are produced, we
78-
* return NULL. (XXX it would probably be more correct to evaluate
79-
* the combining operator with a NULL input?) Assuming we get a tuple:
80-
* if there is only one column then we just return its result as-is, NULL
81-
* or otherwise. If there is more than one column we combine the results
82-
* per "useor" --- this only makes sense if the combining operators yield
83-
* boolean, and we assume the parser has checked that.
85+
* return NULL. Assuming we get a tuple, we just return its first
86+
* column (there can be only one non-junk column in this case).
8487
*/
8588
result= (Datum) (subLinkType==ALL_SUBLINK ? true : false);
8689
*isNull= false;
@@ -98,13 +101,29 @@ ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext, bool *isNull)
98101
if (subLinkType==EXISTS_SUBLINK)
99102
return (Datum) true;
100103

101-
/* cannot allow multiple input tuples for EXPR sublink */
102-
if (subLinkType==EXPR_SUBLINK&&found)
104+
if (subLinkType==EXPR_SUBLINK)
105+
{
106+
/* cannot allow multiple input tuples for EXPR sublink */
107+
if (found)
108+
elog(ERROR,"ExecSubPlan: more than one tuple returned by expression subselect");
109+
found= true;
110+
/* XXX need to copy tuple in case pass by ref */
111+
/* XXX need to ref-count the tuple to avoid mem leak! */
112+
tup=heap_copytuple(tup);
113+
result=heap_getattr(tup,col,tdesc,isNull);
114+
/* keep scanning subplan to make sure there's only one tuple */
115+
continue;
116+
}
117+
118+
/* cannot allow multiple input tuples for MULTIEXPR sublink either */
119+
if (subLinkType==MULTIEXPR_SUBLINK&&found)
103120
elog(ERROR,"ExecSubPlan: more than one tuple returned by expression subselect");
104121

105122
found= true;
106123

107-
/* iterate over combining operators for columns of tuple */
124+
/* For ALL, ANY, and MULTIEXPR sublinks, iterate over combining
125+
* operators for columns of tuple.
126+
*/
108127
foreach(lst,sublink->oper)
109128
{
110129
Expr*expr= (Expr*)lfirst(lst);
@@ -193,7 +212,7 @@ ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext, bool *isNull)
193212
}
194213
else
195214
{
196-
/* must beEXPR_SUBLINK */
215+
/* must beMULTIEXPR_SUBLINK */
197216
result=rowresult;
198217
*isNull=rownull;
199218
}
@@ -202,9 +221,10 @@ ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext, bool *isNull)
202221
if (!found)
203222
{
204223
/* deal with empty subplan result. result/isNull were previously
205-
* initialized correctly for all sublink types except EXPR.
224+
* initialized correctly for all sublink types except EXPR and
225+
* MULTIEXPR; for those, return NULL.
206226
*/
207-
if (subLinkType==EXPR_SUBLINK)
227+
if (subLinkType==EXPR_SUBLINK||subLinkType==MULTIEXPR_SUBLINK)
208228
{
209229
result= (Datum) false;
210230
*isNull= true;
@@ -242,7 +262,7 @@ ExecInitSubPlan(SubPlan *node, EState *estate, Plan *parent)
242262
* If this plan is un-correlated or undirect correlated one and want
243263
* to set params for parent plan then prepare parameters.
244264
*/
245-
if (node->setParam!=NULL)
265+
if (node->setParam!=NIL)
246266
{
247267
List*lst;
248268

@@ -293,24 +313,24 @@ ExecSetParamPlan(SubPlan *node)
293313
TupleDesctdesc=slot->ttc_tupleDescriptor;
294314
inti=1;
295315

296-
if (sublink->subLinkType==EXPR_SUBLINK&&found)
297-
{
298-
elog(ERROR,"ExecSetParamPlan: more than one tuple returned by expression subselect");
299-
return;
300-
}
301-
302-
found= true;
303-
304316
if (sublink->subLinkType==EXISTS_SUBLINK)
305317
{
306318
ParamExecData*prm=&(plan->state->es_param_exec_vals[lfirsti(node->setParam)]);
307319

308320
prm->execPlan=NULL;
309321
prm->value= (Datum) true;
310322
prm->isnull= false;
323+
found= true;
311324
break;
312325
}
313326

327+
if (found&&
328+
(sublink->subLinkType==EXPR_SUBLINK||
329+
sublink->subLinkType==MULTIEXPR_SUBLINK))
330+
elog(ERROR,"ExecSetParamPlan: more than one tuple returned by expression subselect");
331+
332+
found= true;
333+
314334
/*
315335
* If this is uncorrelated subquery then its plan will be closed
316336
* (see below) and this tuple will be free-ed - bad for not byval

‎src/backend/nodes/copyfuncs.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.94 1999/11/01 05:15:13 tgl Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.95 1999/11/15 02:00:01 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -86,10 +86,11 @@ CopyPlanFields(Plan *from, Plan *newnode)
8686
newnode->locParam=listCopy(from->locParam);
8787
newnode->chgParam=listCopy(from->chgParam);
8888
Node_Copy(from,newnode,initPlan);
89-
if (from->subPlan!=NULL)
90-
newnode->subPlan=SS_pull_subplan((Node*)newnode->qual);
89+
if (from->subPlan!=NIL)
90+
newnode->subPlan=nconc(SS_pull_subplan((Node*)newnode->targetlist),
91+
SS_pull_subplan((Node*)newnode->qual));
9192
else
92-
newnode->subPlan=NULL;
93+
newnode->subPlan=NIL;
9394
newnode->nParamExec=from->nParamExec;
9495
}
9596

@@ -137,8 +138,9 @@ _copyResult(Result *from)
137138
* We must add subplans in resconstantqual to the new plan's subPlan
138139
* list
139140
*/
140-
newnode->plan.subPlan=nconc(newnode->plan.subPlan,
141-
SS_pull_subplan(newnode->resconstantqual));
141+
if (from->plan.subPlan!=NIL)
142+
newnode->plan.subPlan=nconc(newnode->plan.subPlan,
143+
SS_pull_subplan(newnode->resconstantqual));
142144

143145
returnnewnode;
144146
}

‎src/backend/optimizer/plan/planmain.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.46 1999/10/07 04:23:06 tgl Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.47 1999/11/15 02:00:07 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -87,9 +87,25 @@ query_planner(Query *root,
8787
tlist= (List*)SS_replace_correlation_vars((Node*)tlist);
8888
qual= (List*)SS_replace_correlation_vars((Node*)qual);
8989
}
90+
9091
/* Expand SubLinks to SubPlans */
9192
if (root->hasSubLinks)
93+
{
94+
tlist= (List*)SS_process_sublinks((Node*)tlist);
9295
qual= (List*)SS_process_sublinks((Node*)qual);
96+
if (root->groupClause!=NIL)
97+
{
98+
/*
99+
* Check for ungrouped variables passed to subplans.
100+
* Note we do NOT do this for subplans in WHERE; it's legal
101+
* there because WHERE is evaluated pre-GROUP.
102+
*/
103+
if (check_subplans_for_ungrouped_vars((Node*)tlist,
104+
root->groupClause,
105+
tlist))
106+
elog(ERROR,"Sub-SELECT must use only GROUPed attributes from outer SELECT");
107+
}
108+
}
93109

94110
/*
95111
* If the query contains no relation references at all, it must be

‎src/backend/optimizer/plan/planner.c

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.70 1999/10/07 04:23:06 tgl Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.71 1999/11/15 02:00:08 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -343,17 +343,11 @@ union_planner(Query *parse)
343343
{
344344
/* Expand SubLinks to SubPlans */
345345
parse->havingQual=SS_process_sublinks(parse->havingQual);
346-
347-
/*
348-
* Check for ungrouped variables passed to subplans. (Probably
349-
* this should be done for the targetlist as well??? But we
350-
* should NOT do it for the WHERE qual, since WHERE is
351-
* evaluated pre-GROUP.)
352-
*/
346+
/* Check for ungrouped variables passed to subplans */
353347
if (check_subplans_for_ungrouped_vars(parse->havingQual,
354348
parse->groupClause,
355349
parse->targetList))
356-
elog(ERROR,"Sub-SELECTin HAVING clausemust use only GROUPed attributes from outer SELECT");
350+
elog(ERROR,"Sub-SELECT must use only GROUPed attributes from outer SELECT");
357351
}
358352
}
359353

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp