Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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)