Skip to content

Commit e549722

Browse files
committed
Get rid of the rather fuzzily defined FlattenedSubLink node type in favor of
making pull_up_sublinks() construct a full-blown JoinExpr tree representation of IN/EXISTS SubLinks that it is able to convert to semi or anti joins. This makes pull_up_sublinks() a shade more complex, but the gain in semantic clarity is worth it. I still have more to do in this area to address the previously-discussed problems, but this commit in itself fixes at least one bug in HEAD, as shown by added regression test case.
1 parent 7380b63 commit e549722

File tree

18 files changed

+299
-497
lines changed

18 files changed

+299
-497
lines changed

src/backend/nodes/copyfuncs.c

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* Portions Copyright (c) 1994, Regents of the University of California
1616
*
1717
* IDENTIFICATION
18-
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.424 2009/02/24 10:06:32 petere Exp $
18+
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.425 2009/02/25 03:30:37 tgl Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -1624,22 +1624,6 @@ _copyRestrictInfo(RestrictInfo *from)
16241624
return newnode;
16251625
}
16261626

1627-
/*
1628-
* _copyFlattenedSubLink
1629-
*/
1630-
static FlattenedSubLink *
1631-
_copyFlattenedSubLink(FlattenedSubLink *from)
1632-
{
1633-
FlattenedSubLink *newnode = makeNode(FlattenedSubLink);
1634-
1635-
COPY_SCALAR_FIELD(jointype);
1636-
COPY_BITMAPSET_FIELD(lefthand);
1637-
COPY_BITMAPSET_FIELD(righthand);
1638-
COPY_NODE_FIELD(quals);
1639-
1640-
return newnode;
1641-
}
1642-
16431627
/*
16441628
* _copyPlaceHolderVar
16451629
*/
@@ -3710,9 +3694,6 @@ copyObject(void *from)
37103694
case T_RestrictInfo:
37113695
retval = _copyRestrictInfo(from);
37123696
break;
3713-
case T_FlattenedSubLink:
3714-
retval = _copyFlattenedSubLink(from);
3715-
break;
37163697
case T_PlaceHolderVar:
37173698
retval = _copyPlaceHolderVar(from);
37183699
break;

src/backend/nodes/equalfuncs.c

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
* Portions Copyright (c) 1994, Regents of the University of California
2323
*
2424
* IDENTIFICATION
25-
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.348 2009/02/24 10:06:32 petere Exp $
25+
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.349 2009/02/25 03:30:37 tgl Exp $
2626
*
2727
*-------------------------------------------------------------------------
2828
*/
@@ -766,17 +766,6 @@ _equalRestrictInfo(RestrictInfo *a, RestrictInfo *b)
766766
return true;
767767
}
768768

769-
static bool
770-
_equalFlattenedSubLink(FlattenedSubLink *a, FlattenedSubLink *b)
771-
{
772-
COMPARE_SCALAR_FIELD(jointype);
773-
COMPARE_BITMAPSET_FIELD(lefthand);
774-
COMPARE_BITMAPSET_FIELD(righthand);
775-
COMPARE_NODE_FIELD(quals);
776-
777-
return true;
778-
}
779-
780769
static bool
781770
_equalPlaceHolderVar(PlaceHolderVar *a, PlaceHolderVar *b)
782771
{
@@ -2496,9 +2485,6 @@ equal(void *a, void *b)
24962485
case T_RestrictInfo:
24972486
retval = _equalRestrictInfo(a, b);
24982487
break;
2499-
case T_FlattenedSubLink:
2500-
retval = _equalFlattenedSubLink(a, b);
2501-
break;
25022488
case T_PlaceHolderVar:
25032489
retval = _equalPlaceHolderVar(a, b);
25042490
break;

src/backend/nodes/nodeFuncs.c

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/nodes/nodeFuncs.c,v 1.37 2009/01/01 17:23:43 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/nodes/nodeFuncs.c,v 1.38 2009/02/25 03:30:37 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -1309,14 +1309,6 @@ expression_tree_walker(Node *node,
13091309
/* groupClauses are deemed uninteresting */
13101310
}
13111311
break;
1312-
case T_FlattenedSubLink:
1313-
{
1314-
FlattenedSubLink *fslink = (FlattenedSubLink *) node;
1315-
1316-
if (walker(fslink->quals, context))
1317-
return true;
1318-
}
1319-
break;
13201312
case T_PlaceHolderVar:
13211313
return walker(((PlaceHolderVar *) node)->phexpr, context);
13221314
case T_AppendRelInfo:
@@ -1972,17 +1964,6 @@ expression_tree_mutator(Node *node,
19721964
return (Node *) newnode;
19731965
}
19741966
break;
1975-
case T_FlattenedSubLink:
1976-
{
1977-
FlattenedSubLink *fslink = (FlattenedSubLink *) node;
1978-
FlattenedSubLink *newnode;
1979-
1980-
FLATCOPY(newnode, fslink, FlattenedSubLink);
1981-
/* Assume we need not copy the relids bitmapsets */
1982-
MUTATE(newnode->quals, fslink->quals, Expr *);
1983-
return (Node *) newnode;
1984-
}
1985-
break;
19861967
case T_PlaceHolderVar:
19871968
{
19881969
PlaceHolderVar *phv = (PlaceHolderVar *) node;

src/backend/nodes/outfuncs.c

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.352 2009/02/06 23:43:23 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.353 2009/02/25 03:30:37 tgl Exp $
1212
*
1313
* NOTES
1414
* Every node type that can appear in stored rules' parsetrees *must*
@@ -1630,17 +1630,6 @@ _outInnerIndexscanInfo(StringInfo str, InnerIndexscanInfo *node)
16301630
WRITE_NODE_FIELD(cheapest_total_innerpath);
16311631
}
16321632

1633-
static void
1634-
_outFlattenedSubLink(StringInfo str, FlattenedSubLink *node)
1635-
{
1636-
WRITE_NODE_TYPE("FLATTENEDSUBLINK");
1637-
1638-
WRITE_ENUM_FIELD(jointype, JoinType);
1639-
WRITE_BITMAPSET_FIELD(lefthand);
1640-
WRITE_BITMAPSET_FIELD(righthand);
1641-
WRITE_NODE_FIELD(quals);
1642-
}
1643-
16441633
static void
16451634
_outPlaceHolderVar(StringInfo str, PlaceHolderVar *node)
16461635
{
@@ -2660,9 +2649,6 @@ _outNode(StringInfo str, void *obj)
26602649
case T_InnerIndexscanInfo:
26612650
_outInnerIndexscanInfo(str, obj);
26622651
break;
2663-
case T_FlattenedSubLink:
2664-
_outFlattenedSubLink(str, obj);
2665-
break;
26662652
case T_PlaceHolderVar:
26672653
_outPlaceHolderVar(str, obj);
26682654
break;

src/backend/optimizer/plan/initsplan.c

Lines changed: 28 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.147 2009/02/20 00:01:03 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.148 2009/02/25 03:30:37 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -52,9 +52,6 @@ static void distribute_qual_to_rels(PlannerInfo *root, Node *clause,
5252
Relids qualscope,
5353
Relids ojscope,
5454
Relids outerjoin_nonnullable);
55-
static void distribute_sublink_quals_to_rels(PlannerInfo *root,
56-
FlattenedSubLink *fslink,
57-
bool below_outer_join);
5855
static bool check_outerjoin_delay(PlannerInfo *root, Relids *relids_p,
5956
bool is_pushed_down);
6057
static bool check_redundant_nullability_qual(PlannerInfo *root, Node *clause);
@@ -336,15 +333,9 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join,
336333
{
337334
Node *qual = (Node *) lfirst(l);
338335

339-
/* FlattenedSubLink wrappers need special processing */
340-
if (qual && IsA(qual, FlattenedSubLink))
341-
distribute_sublink_quals_to_rels(root,
342-
(FlattenedSubLink *) qual,
343-
below_outer_join);
344-
else
345-
distribute_qual_to_rels(root, qual,
346-
false, below_outer_join, JOIN_INNER,
347-
*qualscope, NULL, NULL);
336+
distribute_qual_to_rels(root, qual,
337+
false, below_outer_join, JOIN_INNER,
338+
*qualscope, NULL, NULL);
348339
}
349340
}
350341
else if (IsA(jtnode, JoinExpr))
@@ -399,6 +390,18 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join,
399390
*inner_join_rels = bms_union(left_inners, right_inners);
400391
nonnullable_rels = leftids;
401392
break;
393+
case JOIN_SEMI:
394+
leftjoinlist = deconstruct_recurse(root, j->larg,
395+
below_outer_join,
396+
&leftids, &left_inners);
397+
rightjoinlist = deconstruct_recurse(root, j->rarg,
398+
below_outer_join,
399+
&rightids, &right_inners);
400+
*qualscope = bms_union(leftids, rightids);
401+
*inner_join_rels = bms_union(left_inners, right_inners);
402+
/* Semi join adds no restrictions for quals */
403+
nonnullable_rels = NULL;
404+
break;
402405
case JOIN_FULL:
403406
leftjoinlist = deconstruct_recurse(root, j->larg,
404407
true,
@@ -425,6 +428,9 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join,
425428
* semantic scope (ojscope) to pass to distribute_qual_to_rels. But
426429
* we mustn't add it to join_info_list just yet, because we don't want
427430
* distribute_qual_to_rels to think it is an outer join below us.
431+
*
432+
* Semijoins are a bit of a hybrid: we build a SpecialJoinInfo,
433+
* but we want ojscope = NULL for distribute_qual_to_rels.
428434
*/
429435
if (j->jointype != JOIN_INNER)
430436
{
@@ -433,7 +439,11 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join,
433439
*inner_join_rels,
434440
j->jointype,
435441
(List *) j->quals);
436-
ojscope = bms_union(sjinfo->min_lefthand, sjinfo->min_righthand);
442+
if (j->jointype == JOIN_SEMI)
443+
ojscope = NULL;
444+
else
445+
ojscope = bms_union(sjinfo->min_lefthand,
446+
sjinfo->min_righthand);
437447
}
438448
else
439449
{
@@ -446,16 +456,10 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join,
446456
{
447457
Node *qual = (Node *) lfirst(l);
448458

449-
/* FlattenedSubLink wrappers need special processing */
450-
if (qual && IsA(qual, FlattenedSubLink))
451-
distribute_sublink_quals_to_rels(root,
452-
(FlattenedSubLink *) qual,
453-
below_outer_join);
454-
else
455-
distribute_qual_to_rels(root, qual,
456-
false, below_outer_join, j->jointype,
457-
*qualscope,
458-
ojscope, nonnullable_rels);
459+
distribute_qual_to_rels(root, qual,
460+
false, below_outer_join, j->jointype,
461+
*qualscope,
462+
ojscope, nonnullable_rels);
459463
}
460464

461465
/* Now we can add the SpecialJoinInfo to join_info_list */
@@ -1044,64 +1048,6 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
10441048
distribute_restrictinfo_to_rels(root, restrictinfo);
10451049
}
10461050

1047-
/*
1048-
* distribute_sublink_quals_to_rels
1049-
* Pull sublink quals out of a FlattenedSubLink node and distribute
1050-
* them appropriately; then add a SpecialJoinInfo node to the query's
1051-
* join_info_list. The FlattenedSubLink node itself is no longer
1052-
* needed and does not propagate into further processing.
1053-
*/
1054-
static void
1055-
distribute_sublink_quals_to_rels(PlannerInfo *root,
1056-
FlattenedSubLink *fslink,
1057-
bool below_outer_join)
1058-
{
1059-
List *quals = make_ands_implicit(fslink->quals);
1060-
SpecialJoinInfo *sjinfo;
1061-
Relids qualscope;
1062-
Relids ojscope;
1063-
Relids outerjoin_nonnullable;
1064-
ListCell *l;
1065-
1066-
/*
1067-
* Build a suitable SpecialJoinInfo for the sublink. Note: using
1068-
* righthand as inner_join_rels is the conservative worst case;
1069-
* it might be possible to use a smaller set and thereby allow
1070-
* the sublink join to commute with others inside its RHS.
1071-
*/
1072-
sjinfo = make_outerjoininfo(root,
1073-
fslink->lefthand, fslink->righthand,
1074-
fslink->righthand,
1075-
fslink->jointype,
1076-
quals);
1077-
1078-
/* Treat as inner join if SEMI, outer join if ANTI */
1079-
qualscope = bms_union(sjinfo->syn_lefthand, sjinfo->syn_righthand);
1080-
if (fslink->jointype == JOIN_SEMI)
1081-
{
1082-
ojscope = outerjoin_nonnullable = NULL;
1083-
}
1084-
else
1085-
{
1086-
Assert(fslink->jointype == JOIN_ANTI);
1087-
ojscope = bms_union(sjinfo->min_lefthand, sjinfo->min_righthand);
1088-
outerjoin_nonnullable = fslink->lefthand;
1089-
}
1090-
1091-
/* Distribute the join quals much as for a regular JOIN node */
1092-
foreach(l, quals)
1093-
{
1094-
Node *qual = (Node *) lfirst(l);
1095-
1096-
distribute_qual_to_rels(root, qual,
1097-
false, below_outer_join, fslink->jointype,
1098-
qualscope, ojscope, outerjoin_nonnullable);
1099-
}
1100-
1101-
/* Now we can add the SpecialJoinInfo to join_info_list */
1102-
root->join_info_list = lappend(root->join_info_list, sjinfo);
1103-
}
1104-
11051051
/*
11061052
* check_outerjoin_delay
11071053
* Detect whether a qual referencing the given relids must be delayed

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy