<feed xmlns='http://www.w3.org/2005/Atom'>
<title>delta/postgresql.git/src/test/regress/expected/join_1.out, branch master</title>
<subtitle>git.postgresql.org: git/postgresql.git
</subtitle>
<link rel='alternate' type='text/html' href='http://trove.baserock.org/cgit/delta/postgresql.git/'/>
<entry>
<title>Remove outdated join_1.out regression test comparison file.  This has</title>
<updated>2009-02-26T22:19:20+00:00</updated>
<author>
<name>Tom Lane</name>
<email>tgl@sss.pgh.pa.us</email>
</author>
<published>2009-02-26T22:19:20+00:00</published>
<link rel='alternate' type='text/html' href='http://trove.baserock.org/cgit/delta/postgresql.git/commit/?id=f4fea44ce15ce8a036faf8594c140dc02825dc0c'/>
<id>f4fea44ce15ce8a036faf8594c140dc02825dc0c</id>
<content type='text'>
been broken for more than a month, so evidently it's not needed, at
least not for any configuration in the buildfarm.  We can correct it
and replace it later if we find something that still needs it.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
been broken for more than a month, so evidently it's not needed, at
least not for any configuration in the buildfarm.  We can correct it
and replace it later if we find something that still needs it.
</pre>
</div>
</content>
</entry>
<entry>
<title>Get rid of the rather fuzzily defined FlattenedSubLink node type in favor of</title>
<updated>2009-02-25T03:30:38+00:00</updated>
<author>
<name>Tom Lane</name>
<email>tgl@sss.pgh.pa.us</email>
</author>
<published>2009-02-25T03:30:38+00:00</published>
<link rel='alternate' type='text/html' href='http://trove.baserock.org/cgit/delta/postgresql.git/commit/?id=e549722a8b2fcc5b2ad9a9bd53948466ea5dae26'/>
<id>e549722a8b2fcc5b2ad9a9bd53948466ea5dae26</id>
<content type='text'>
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.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
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.
</pre>
</div>
</content>
</entry>
<entry>
<title>Consider a clause to be outerjoin_delayed if it references the nullable side</title>
<updated>2008-06-27T20:54:37+00:00</updated>
<author>
<name>Tom Lane</name>
<email>tgl@sss.pgh.pa.us</email>
</author>
<published>2008-06-27T20:54:37+00:00</published>
<link rel='alternate' type='text/html' href='http://trove.baserock.org/cgit/delta/postgresql.git/commit/?id=dcc23347365d1958898445ffdcf34c09689b8d55'/>
<id>dcc23347365d1958898445ffdcf34c09689b8d55</id>
<content type='text'>
of any lower outer join, even if it also references the non-nullable side and
so could not get pushed below the outer join anyway.  We need this in case
the clause is an OR clause: if it doesn't get marked outerjoin_delayed,
create_or_index_quals() could pull an indexable restriction for the nullable
side out of it, leading to wrong results as demonstrated by today's bug
report from toruvinn.  (See added regression test case for an example.)

In principle this has been wrong for quite a while.  In practice I don't
think any branch before 8.3 can really show the failure, because
create_or_index_quals() will only pull out indexable conditions, and before
8.3 those were always strict.  So though we might have improperly generated
null-extended rows in the outer join, they'd get discarded from the result
anyway.  The gating factor that makes the failure visible is that 8.3
considers "col IS NULL" to be indexable.  Hence I'm not going to risk
back-patching further than 8.3.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
of any lower outer join, even if it also references the non-nullable side and
so could not get pushed below the outer join anyway.  We need this in case
the clause is an OR clause: if it doesn't get marked outerjoin_delayed,
create_or_index_quals() could pull an indexable restriction for the nullable
side out of it, leading to wrong results as demonstrated by today's bug
report from toruvinn.  (See added regression test case for an example.)

In principle this has been wrong for quite a while.  In practice I don't
think any branch before 8.3 can really show the failure, because
create_or_index_quals() will only pull out indexable conditions, and before
8.3 those were always strict.  So though we might have improperly generated
null-extended rows in the outer join, they'd get discarded from the result
anyway.  The gating factor that makes the failure visible is that 8.3
considers "col IS NULL" to be indexable.  Hence I'm not going to risk
back-patching further than 8.3.
</pre>
</div>
</content>
</entry>
<entry>
<title>Fix some planner issues found while investigating Kevin Grittner's report</title>
<updated>2008-01-09T20:42:29+00:00</updated>
<author>
<name>Tom Lane</name>
<email>tgl@sss.pgh.pa.us</email>
</author>
<published>2008-01-09T20:42:29+00:00</published>
<link rel='alternate' type='text/html' href='http://trove.baserock.org/cgit/delta/postgresql.git/commit/?id=6a6522529fb0c1b42050f322d37d91df14d7994c'/>
<id>6a6522529fb0c1b42050f322d37d91df14d7994c</id>
<content type='text'>
of poorer planning in 8.3 than 8.2:

1. After pushing a constant across an outer join --- ie, given
"a LEFT JOIN b ON (a.x = b.y) WHERE a.x = 42", we can deduce that b.y is
sort of equal to 42, in the sense that we needn't fetch any b rows where
it isn't 42 --- loop to see if any additional deductions can be made.
Previous releases did that by recursing, but I had mistakenly thought that
this was no longer necessary given the EquivalenceClass machinery.

2. Allow pushing constants across outer join conditions even if the
condition is outerjoin_delayed due to a lower outer join.  This is safe
as long as the condition is strict and we re-test it at the upper join.

3. Keep the outer-join clause even if we successfully push a constant
across it.  This is *necessary* in the outerjoin_delayed case, but
even in the simple case, it seems better to do this to ensure that the
join search order heuristics will consider the join as reasonable to
make.  Mark such a clause as having selectivity 1.0, though, since it's
not going to eliminate very many rows after application of the constant
condition.

4. Tweak have_relevant_eclass_joinclause to report that two relations
are joinable when they have vars that are equated to the same constant.
We won't actually generate any joinclause from such an EquivalenceClass,
but again it seems that in such a case it's a good idea to consider
the join as worth costing out.

5. Fix a bug in select_mergejoin_clauses that was exposed by these
changes: we have to reject candidate mergejoin clauses if either side was
equated to a constant, because we can't construct a canonical pathkey list
for such a clause.  This is an implementation restriction that might be
worth fixing someday, but it doesn't seem critical to get it done for 8.3.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
of poorer planning in 8.3 than 8.2:

1. After pushing a constant across an outer join --- ie, given
"a LEFT JOIN b ON (a.x = b.y) WHERE a.x = 42", we can deduce that b.y is
sort of equal to 42, in the sense that we needn't fetch any b rows where
it isn't 42 --- loop to see if any additional deductions can be made.
Previous releases did that by recursing, but I had mistakenly thought that
this was no longer necessary given the EquivalenceClass machinery.

2. Allow pushing constants across outer join conditions even if the
condition is outerjoin_delayed due to a lower outer join.  This is safe
as long as the condition is strict and we re-test it at the upper join.

3. Keep the outer-join clause even if we successfully push a constant
across it.  This is *necessary* in the outerjoin_delayed case, but
even in the simple case, it seems better to do this to ensure that the
join search order heuristics will consider the join as reasonable to
make.  Mark such a clause as having selectivity 1.0, though, since it's
not going to eliminate very many rows after application of the constant
condition.

4. Tweak have_relevant_eclass_joinclause to report that two relations
are joinable when they have vars that are equated to the same constant.
We won't actually generate any joinclause from such an EquivalenceClass,
but again it seems that in such a case it's a good idea to consider
the join as worth costing out.

5. Fix a bug in select_mergejoin_clauses that was exposed by these
changes: we have to reject candidate mergejoin clauses if either side was
equated to a constant, because we can't construct a canonical pathkey list
for such a clause.  This is an implementation restriction that might be
worth fixing someday, but it doesn't seem critical to get it done for 8.3.
</pre>
</div>
</content>
</entry>
<entry>
<title>Rewrite make_outerjoininfo's construction of min_lefthand and min_righthand</title>
<updated>2007-08-31T01:44:06+00:00</updated>
<author>
<name>Tom Lane</name>
<email>tgl@sss.pgh.pa.us</email>
</author>
<published>2007-08-31T01:44:06+00:00</published>
<link rel='alternate' type='text/html' href='http://trove.baserock.org/cgit/delta/postgresql.git/commit/?id=b4c806faa8cb8aa54599265e5d94d7b3139e9750'/>
<id>b4c806faa8cb8aa54599265e5d94d7b3139e9750</id>
<content type='text'>
sets for outer joins, in the light of bug #3588 and additional thought and
experimentation.  The original methodology was fatally flawed for nests of
more than two outer joins: it got the relationships between adjacent joins
right, but didn't always come to the right conclusions about whether a join
could be interchanged with one two or more levels below it.  This was largely
caused by a mistaken idea that we should use the min_lefthand + min_righthand
sets of a sub-join as the minimum left or right input set of an upper join
when we conclude that the sub-join can't commute with the upper one.  If
there's a still-lower join that the sub-join *can* commute with, this method
led us to think that that one could commute with the topmost join; which it
can't.  Another problem (not directly connected to bug #3588) was that
make_outerjoininfo's processing-order-dependent method for enforcing outer
join identity #3 didn't work right: if we decided that join A could safely
commute with lower join B, we dropped all information about sub-joins under B
that join A could perhaps not safely commute with, because we removed B's
entire min_righthand from A's.

To fix, make an explicit computation of all inner join combinations that occur
below an outer join, and add to that the full syntactic relsets of any lower
outer joins that we determine it can't commute with.  This method gives much
more direct enforcement of the outer join rearrangement identities, and it
turns out not to cost a lot of additional bookkeeping.

Thanks to Richard Harris for the bug report and test case.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
sets for outer joins, in the light of bug #3588 and additional thought and
experimentation.  The original methodology was fatally flawed for nests of
more than two outer joins: it got the relationships between adjacent joins
right, but didn't always come to the right conclusions about whether a join
could be interchanged with one two or more levels below it.  This was largely
caused by a mistaken idea that we should use the min_lefthand + min_righthand
sets of a sub-join as the minimum left or right input set of an upper join
when we conclude that the sub-join can't commute with the upper one.  If
there's a still-lower join that the sub-join *can* commute with, this method
led us to think that that one could commute with the topmost join; which it
can't.  Another problem (not directly connected to bug #3588) was that
make_outerjoininfo's processing-order-dependent method for enforcing outer
join identity #3 didn't work right: if we decided that join A could safely
commute with lower join B, we dropped all information about sub-joins under B
that join A could perhaps not safely commute with, because we removed B's
entire min_righthand from A's.

To fix, make an explicit computation of all inner join combinations that occur
below an outer join, and add to that the full syntactic relsets of any lower
outer joins that we determine it can't commute with.  This method gives much
more direct enforcement of the outer join rearrangement identities, and it
turns out not to cost a lot of additional bookkeeping.

Thanks to Richard Harris for the bug report and test case.
</pre>
</div>
</content>
</entry>
<entry>
<title>Fix a bug in the original implementation of redundant-join-clause removal:</title>
<updated>2007-07-31T19:53:37+00:00</updated>
<author>
<name>Tom Lane</name>
<email>tgl@sss.pgh.pa.us</email>
</author>
<published>2007-07-31T19:53:37+00:00</published>
<link rel='alternate' type='text/html' href='http://trove.baserock.org/cgit/delta/postgresql.git/commit/?id=ed5d55dafe96627fe810dec80ccba98df0b6834b'/>
<id>ed5d55dafe96627fe810dec80ccba98df0b6834b</id>
<content type='text'>
clauses in which one side or the other references both sides of the join
cannot be removed as redundant, because that expression won't have been
constrained below the join.  Per report from Sergey Burladyan.

CVS HEAD does not contain this bug due to EquivalenceClass rewrite, but it
seems wise to include the regression test for it anyway.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
clauses in which one side or the other references both sides of the join
cannot be removed as redundant, because that expression won't have been
constrained below the join.  Per report from Sergey Burladyan.

CVS HEAD does not contain this bug due to EquivalenceClass rewrite, but it
seems wise to include the regression test for it anyway.
</pre>
</div>
</content>
</entry>
<entry>
<title>Repair planner bug introduced in 8.2 by ability to rearrange outer joins:</title>
<updated>2007-05-22T23:23:58+00:00</updated>
<author>
<name>Tom Lane</name>
<email>tgl@sss.pgh.pa.us</email>
</author>
<published>2007-05-22T23:23:58+00:00</published>
<link rel='alternate' type='text/html' href='http://trove.baserock.org/cgit/delta/postgresql.git/commit/?id=11086f2f2bfec3a5fd37daf3c2e44b51abaf9b69'/>
<id>11086f2f2bfec3a5fd37daf3c2e44b51abaf9b69</id>
<content type='text'>
in cases where a sub-SELECT inserts a WHERE clause between two outer joins,
that clause may prevent us from re-ordering the two outer joins.  The code
was considering only the joins' own ON-conditions in determining reordering
safety, which is not good enough.  Add a "delay_upper_joins" flag to
OuterJoinInfo to flag that we have detected such a clause and higher-level
outer joins shouldn't be permitted to commute with this one.  (This might
seem overly coarse, but given the current rules for OJ reordering, it's
sufficient AFAICT.)

The failure case is actually pretty narrow: it needs a WHERE clause within
the RHS of a left join that checks the RHS of a lower left join, but is not
strict for that RHS (else we'd have simplified the lower join to a plain
join).  Even then no failure will be manifest unless the planner chooses to
rearrange the join order.

Per bug report from Adam Terrey.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
in cases where a sub-SELECT inserts a WHERE clause between two outer joins,
that clause may prevent us from re-ordering the two outer joins.  The code
was considering only the joins' own ON-conditions in determining reordering
safety, which is not good enough.  Add a "delay_upper_joins" flag to
OuterJoinInfo to flag that we have detected such a clause and higher-level
outer joins shouldn't be permitted to commute with this one.  (This might
seem overly coarse, but given the current rules for OJ reordering, it's
sufficient AFAICT.)

The failure case is actually pretty narrow: it needs a WHERE clause within
the RHS of a left join that checks the RHS of a lower left join, but is not
strict for that RHS (else we'd have simplified the lower join to a plain
join).  Even then no failure will be manifest unless the planner chooses to
rearrange the join order.

Per bug report from Adam Terrey.
</pre>
</div>
</content>
</entry>
<entry>
<title>Restructure code that is responsible for ensuring that clauseless joins are</title>
<updated>2007-02-16T00:14:01+00:00</updated>
<author>
<name>Tom Lane</name>
<email>tgl@sss.pgh.pa.us</email>
</author>
<published>2007-02-16T00:14:01+00:00</published>
<link rel='alternate' type='text/html' href='http://trove.baserock.org/cgit/delta/postgresql.git/commit/?id=6bef118b01ec541440fccf8ce3641fd025297de0'/>
<id>6bef118b01ec541440fccf8ce3641fd025297de0</id>
<content type='text'>
considered when it is necessary to do so because of a join-order restriction
(that is, an outer-join or IN-subselect construct).  The former coding was a
bit ad-hoc and inconsistent, and it missed some cases, as exposed by Mario
Weilguni's recent bug report.  His specific problem was that an IN could be
turned into a "clauseless" join due to constant-propagation removing the IN's
joinclause, and if the IN's subselect involved more than one relation and
there was more than one such IN linking to the same upper relation, then the
only valid join orders involve "bushy" plans but we would fail to consider the
specific paths needed to get there.  (See the example case added to the join
regression test.)  On examining the code I wonder if there weren't some other
problem cases too; in particular it seems that GEQO was defending against a
different set of corner cases than the main planner was.  There was also an
efficiency problem, in that when we did realize we needed a clauseless join
because of an IN, we'd consider clauseless joins against every other relation
whether this was sensible or not.  It seems a better design is to use the
outer-join and in-clause lists as a backup heuristic, just as the rule of
joining only where there are joinclauses is a heuristic: we'll join two
relations if they have a usable joinclause *or* this might be necessary to
satisfy an outer-join or IN-clause join order restriction.  I refactored the
code to have just one place considering this instead of three, and made sure
that it covered all the cases that any of them had been considering.

Backpatch as far as 8.1 (which has only the IN-clause form of the disease).
By rights 8.0 and 7.4 should have the bug too, but they accidentally fail
to fail, because the joininfo structure used in those releases preserves some
memory of there having once been a joinclause between the inner and outer
sides of an IN, and so it leads the code in the right direction anyway.
I'll be conservative and not touch them.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
considered when it is necessary to do so because of a join-order restriction
(that is, an outer-join or IN-subselect construct).  The former coding was a
bit ad-hoc and inconsistent, and it missed some cases, as exposed by Mario
Weilguni's recent bug report.  His specific problem was that an IN could be
turned into a "clauseless" join due to constant-propagation removing the IN's
joinclause, and if the IN's subselect involved more than one relation and
there was more than one such IN linking to the same upper relation, then the
only valid join orders involve "bushy" plans but we would fail to consider the
specific paths needed to get there.  (See the example case added to the join
regression test.)  On examining the code I wonder if there weren't some other
problem cases too; in particular it seems that GEQO was defending against a
different set of corner cases than the main planner was.  There was also an
efficiency problem, in that when we did realize we needed a clauseless join
because of an IN, we'd consider clauseless joins against every other relation
whether this was sensible or not.  It seems a better design is to use the
outer-join and in-clause lists as a backup heuristic, just as the rule of
joining only where there are joinclauses is a heuristic: we'll join two
relations if they have a usable joinclause *or* this might be necessary to
satisfy an outer-join or IN-clause join order restriction.  I refactored the
code to have just one place considering this instead of three, and made sure
that it covered all the cases that any of them had been considering.

Backpatch as far as 8.1 (which has only the IN-clause form of the disease).
By rights 8.0 and 7.4 should have the bug too, but they accidentally fail
to fail, because the joininfo structure used in those releases preserves some
memory of there having once been a joinclause between the inner and outer
sides of an IN, and so it leads the code in the right direction anyway.
I'll be conservative and not touch them.
</pre>
</div>
</content>
</entry>
<entry>
<title>Adjust join_1.out to match Windows behavior for new mergejoin regression</title>
<updated>2006-03-19T01:19:42+00:00</updated>
<author>
<name>Tom Lane</name>
<email>tgl@sss.pgh.pa.us</email>
</author>
<published>2006-03-19T01:19:42+00:00</published>
<link rel='alternate' type='text/html' href='http://trove.baserock.org/cgit/delta/postgresql.git/commit/?id=381cb046ed60a1164a244e2f9aa28b8128ea2ac5'/>
<id>381cb046ed60a1164a244e2f9aa28b8128ea2ac5</id>
<content type='text'>
test, per Dave Page and buildfarm.  Perhaps we will need a join_2 instead,
but for the moment assume that this test tracks the other diffs.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
test, per Dave Page and buildfarm.  Perhaps we will need a join_2 instead,
but for the moment assume that this test tracks the other diffs.
</pre>
</div>
</content>
</entry>
<entry>
<title>Fix bug introduced into mergejoin logic by performance improvement patch of</title>
<updated>2006-03-17T19:38:12+00:00</updated>
<author>
<name>Tom Lane</name>
<email>tgl@sss.pgh.pa.us</email>
</author>
<published>2006-03-17T19:38:12+00:00</published>
<link rel='alternate' type='text/html' href='http://trove.baserock.org/cgit/delta/postgresql.git/commit/?id=b3358e2642d397e5e1d25ceade09c0749623e3a1'/>
<id>b3358e2642d397e5e1d25ceade09c0749623e3a1</id>
<content type='text'>
2005-05-13.  When we find that a new inner tuple can't possibly match any
outer tuple (because it contains a NULL), we can't immediately skip the
tuple when we are in NEXTINNER state.  Doing so can lead to emitting
multiple copies of the tuple in FillInner mode, because we may rescan the
tuple after returning to a previous marked tuple.  Instead, proceed to
NEXTOUTER state the same as we used to do.  After we've found that there's
no need to return to the marked position, we can go to SKIPINNER_ADVANCE
state instead of SKIP_TEST when the inner tuple is unmatchable; this
preserves the performance improvement.  Per bug report from Bruce.
I also made a couple of cosmetic code rearrangements and added a regression
test for the problem.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
2005-05-13.  When we find that a new inner tuple can't possibly match any
outer tuple (because it contains a NULL), we can't immediately skip the
tuple when we are in NEXTINNER state.  Doing so can lead to emitting
multiple copies of the tuple in FillInner mode, because we may rescan the
tuple after returning to a previous marked tuple.  Instead, proceed to
NEXTOUTER state the same as we used to do.  After we've found that there's
no need to return to the marked position, we can go to SKIPINNER_ADVANCE
state instead of SKIP_TEST when the inner tuple is unmatchable; this
preserves the performance improvement.  Per bug report from Bruce.
I also made a couple of cosmetic code rearrangements and added a regression
test for the problem.
</pre>
</div>
</content>
</entry>
</feed>
