Thread: ERROR: failed to build any 4-way joins

ERROR: failed to build any 4-way joins

From
Teodor Sigaev
Date:
Test suite (as simple as I can produce):
CREATE TABLE foo (a int, b int);

INSERT INTO foo VALUES (1,2);
INSERT INTO foo VALUES (2,3);
INSERT INTO foo VALUES (3,3);

CREATE VIEW fooview AS
     SELECT
             f1.a AS a_for_max_b
     FROM
         ( SELECT MAX(foo.b) AS MaxB FROM foo ) f2
         INNER JOIN foo f1
             ON f2.MaxB = f1.b;


And this query fails:
SELECT
     *
FROM
     fooview fv1
     LEFT OUTER JOIN fooview fv2
         ON TRUE = TRUE;

It also fails with RIGHT join, but it doesn't fail with INNER or FULL joins.

If view is defined (essentially the same) as
CREATE VIEW fooview AS
     SELECT
         f1.a AS a_for_max_b
     FROM
         foo f1
     WHERE
         f1.b = (SELECT MAX(f2.b) FROM foo f2);
then all is ok.


--
Teodor Sigaev                                   E-mail: teodor@sigaev.ru
                                                 WWW: http://www.sigaev.ru/

Re: ERROR: failed to build any 4-way joins

From
Teodor Sigaev
Date:
Sorry, versions are 8.2 & 8.3. 8.1 works well


--
Teodor Sigaev                                   E-mail: teodor@sigaev.ru
                                                    WWW: http://www.sigaev.ru/

Re: ERROR: failed to build any 4-way joins

From
Tom Lane
Date:
Teodor Sigaev <teodor@sigaev.ru> writes:
> Test suite (as simple as I can produce):

Mmm, sweet :-(.  There is only one legal way to form the outer join, but
make_rels_by_joins() doesn't try it because have_relevant_joinclause()
says there is no relevant joinclause ... as indeed there is not, the
"true = true" thing having been optimized away.  I guess we need a hack
to treat empty outer join conditions specially.

> Sorry, versions are 8.2 & 8.3. 8.1 works well

Right, not a problem before 8.2 because outer join order was driven by
the syntax instead of by searching for a good join order.  Also, you
need at least two base relations on each side of the outer join, else
the "last ditch" case in make_rels_by_joins() finds the join.

            regards, tom lane

Re: ERROR: failed to build any 4-way joins

From
Tom Lane
Date:
I wrote:
> I guess we need a hack
> to treat empty outer join conditions specially.

Actually, it can happen with non-empty join conditions too, if the join
condition doesn't mention the outer side; for instance, using your
example

explain SELECT * from fooview fv1
   LEFT OUTER JOIN fooview fv2 on fv2.a_for_max_b < 10;

So my original thoughts of a narrow special case for "OUTER JOIN ON TRUE"
went up in smoke, and I ended up just having have_relevant_joinclause()
troll for relevant outer joins all the time.  This probably isn't going
to cost enough planning time to matter, anyway.

            regards, tom lane

Re: ERROR: failed to build any 4-way joins

From
Teodor Sigaev
Date:
> went up in smoke, and I ended up just having have_relevant_joinclause()

Thank you a lot, I was near around it :)

--
Teodor Sigaev                                   E-mail: teodor@sigaev.ru
                                                    WWW: http://www.sigaev.ru/