1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-20 05:03:10 +03:00

Improve predtest.c's handling of cases with NULL-constant inputs.

Currently, if operator_predicate_proof() is given an operator clause like
"something op NULL", it just throws up its hands and reports it can't prove
anything.  But we can often do better than that, if the operator is strict,
because then we know that the clause returns NULL overall.  Depending on
whether we're trying to prove or refute something, and whether we need
weak or strong semantics for NULL, this may be enough to prove the
implication, especially when we rely on the standard rule that "false
implies anything".  In particular, this lets us do something useful with
questions like "does X IN (1,3,5,NULL) imply X <= 5?"  The null entry
in the IN list can effectively be ignored for this purpose, but the
proof rules were not previously smart enough to deduce that.

This patch is by me, but it owes something to previous work by
Amit Langote to try to solve problems of the form mentioned.
Thanks also to Emre Hasegeli and Ashutosh Bapat for review.

Discussion: https://postgr.es/m/3bad48fc-f257-c445-feeb-8a2b2fb622ba@lab.ntt.co.jp
This commit is contained in:
Tom Lane
2018-03-21 18:30:46 -04:00
parent 27ba260c73
commit 0f0deb7194
4 changed files with 46 additions and 23 deletions

View File

@ -781,13 +781,12 @@ w_i_holds | f
s_r_holds | f
w_r_holds | f
-- XXX ideally, we could prove this case too, for strong implication
select * from test_predtest($$
select x <= 5, x in (1,3,5,null)
from integers
$$);
-[ RECORD 1 ]-----+--
strong_implied_by | f
strong_implied_by | t
weak_implied_by | f
strong_refuted_by | f
weak_refuted_by | f

View File

@ -306,7 +306,6 @@ select x <= 5, x in (1,3,5,7)
from integers
$$);
-- XXX ideally, we could prove this case too, for strong implication
select * from test_predtest($$
select x <= 5, x in (1,3,5,null)
from integers

View File

@ -1739,11 +1739,7 @@ explain (costs off) select * from list_parted where a = 'ab' or a in (null, 'cd'
Append
-> Seq Scan on part_ab_cd
Filter: (((a)::text = 'ab'::text) OR ((a)::text = ANY ('{NULL,cd}'::text[])))
-> Seq Scan on part_ef_gh
Filter: (((a)::text = 'ab'::text) OR ((a)::text = ANY ('{NULL,cd}'::text[])))
-> Seq Scan on part_null_xy
Filter: (((a)::text = 'ab'::text) OR ((a)::text = ANY ('{NULL,cd}'::text[])))
(7 rows)
(3 rows)
explain (costs off) select * from list_parted where a = 'ab';
QUERY PLAN