Re: apply outer->inner join optimisation to OR clauses - Mailing list pgsql-patches

From Tom Lane
Subject Re: apply outer->inner join optimisation to OR clauses
Date
Msg-id 20085.1052009594@sss.pgh.pa.us
Whole thread Raw
In response to Re: apply outer->inner join optimisation to OR clauses  (Bradley Baetz <bbaetz@acm.org>)
Responses Re: apply outer->inner join optimisation to OR clauses
Re: apply outer->inner join optimisation to OR clauses
List pgsql-patches
Bradley Baetz <bbaetz@acm.org> writes:
> I don't think that the fact that |SELECT foo>2 OR NULL| gives NULL, not
> FALSE, if foo <=2 is an issue either, since they're both not a true
> value.

But that is exactly the distinction that we have to worry about when not
at top level.  The error in the AND part of the proposed patch is
exhibited by
        WHERE NOT ((a.a1 > 1) AND (b.b1 > 1))
When a.a1 is NULL, the AND can't yield TRUE --- but it can yield FALSE,
which will become TRUE at the top level.  So neither a nor b can be
considered non-nullable in this expression.

You do have an insight here, which is that if the same rel can be shown
to null *all* the arms of an OR, it nulls the OR.  The same holds true
of an AND, I think.

You might be right that passing top_level through the AND or OR would be
safe in the present state of the code, but it strikes me as fragile and
confusing to leave it that way, because it no longer means what its name
implies and the comments say.  ISTM what we need to do if we want to
extend this code is to come up with a stronger definition of the context
in which each recursive level gets invoked.  I think it might work to
define a three-way context value instead of a boolean:

SAFE_IF_NULL        a rel is nonnullable if nulling it forces this
            expression to return NULL
SAFE_IF_NULL_OR_FALSE    a rel is nonnullable if nulling it forces this
            expression to return NULL or FALSE
SAFE_IF_NULL_OR_TRUE    a rel is nonnullable if nulling it forces this
            expression to return NULL or TRUE

The present notion of top-level would be replaced by context
SAFE_IF_NULL_OR_FALSE.  Descent through a strict operator or function
always narrows the context to SAFE_IF_NULL (since we don't know what
the op/func might do with other values, and we can't even be sure we're
talking about booleans anymore anyway).  Descent through NOT exchanges
SAFE_IF_NULL_OR_FALSE and SAFE_IF_NULL_OR_TRUE.  You could make
appropriate extensions of the code for NullTest and BooleanTest, and
I think this would allow sane handling of the AND and OR cases: for
example, AND with SAFE_IF_NULL_OR_FALSE context really can union the
inputs' nonnullable sets (since forcing any one input to null or false
guarantees the AND result is null or false) but AND in the other
contexts has to intersect the inputs' sets.  I think also that AND and
OR might be able to pass down more liberal contexts than they get,
but am not sure about that part.

(BTW, I don't quite like the adjective SAFE here; can you think of a
better term?)

The SAFE_IF_NULL_OR_TRUE context might prove not to be worth the trouble
of implementing --- I'm not sure if either AND or OR can really exploit
it any better than they can exploit SAFE_IS_NULL.  If not, we'd be back
to just a boolean context value, but we'd have a clearer understanding
of what it really means.

I don't have time to slog through the details, but if you want to run
with that, go for it ...

            regards, tom lane


pgsql-patches by date:

Previous
From: Bradley Baetz
Date:
Subject: Re: apply outer->inner join optimisation to OR clauses
Next
From: Bradley Baetz
Date:
Subject: Re: apply outer->inner join optimisation to OR clauses