mirror of
https://github.com/postgres/postgres.git
synced 2025-07-20 05:03:10 +03:00
Improve predtest.c's internal docs, and enhance its functionality a bit.
Commitb08df9cab
left things rather poorly documented as far as the exact semantics of "clause_is_check" mode went. Also, that mode did not really work correctly for predicate_refuted_by; although given the lack of specification as to what it should do, as well as the lack of any actual use-case, that's perhaps not surprising. Rename "clause_is_check" to "weak" proof mode, and provide specifications for what it should do. I defined weak refutation as meaning "truth of A implies non-truth of B", which makes it possible to use the mode in the part of relation_excluded_by_constraints that checks for mutually contradictory WHERE clauses. Fix up several places that did things wrong for that definition. (As far as I can see, these errors would only lead to failure-to-prove, not incorrect claims of proof, making them not serious bugs even aside from the fact that v10 contains no use of this mode. So there seems no need for back-patching.) In addition, teach predicate_refuted_by_recurse that it can use predicate_implied_by_recurse after all when processing a strong NOT-clause, so long as it asks for the correct proof strength. This is an optimization that could have been included in commitb08df9cab
, but wasn't. Also, simplify and generalize the logic that checks for whether nullness of the argument of IS [NOT] NULL would force overall nullness of the predicate or clause. (This results in a change in the partition_prune test's output, as it is now able to prune an all-nulls partition that it did not recognize before.) In passing, in PartConstraintImpliedByRelConstraint, remove bogus conversion of the constraint list to explicit-AND form and then right back again; that accomplished nothing except forcing a useless extra level of recursion inside predicate_implied_by. Discussion: https://postgr.es/m/5983.1520487191@sss.pgh.pa.us
This commit is contained in:
@ -16,6 +16,9 @@ select
|
||||
case i%11 when 10 then null else i%11 end as x,
|
||||
case (i/11)%11 when 10 then null else (i/11)%11 end as y
|
||||
from generate_series(0, 11*11-1) i;
|
||||
-- and a simple strict function that's opaque to the optimizer
|
||||
create function strictf(bool, bool) returns bool
|
||||
language plpgsql as $$begin return $1 and not $2; end$$ strict;
|
||||
-- Basic proof rules for single boolean variables
|
||||
select * from test_predtest($$
|
||||
select x, x
|
||||
@ -109,7 +112,7 @@ $$);
|
||||
strong_implied_by | f
|
||||
weak_implied_by | f
|
||||
strong_refuted_by | t
|
||||
weak_refuted_by | f
|
||||
weak_refuted_by | t
|
||||
s_i_holds | f
|
||||
w_i_holds | f
|
||||
s_r_holds | t
|
||||
@ -199,7 +202,7 @@ w_i_holds | t
|
||||
s_r_holds | f
|
||||
w_r_holds | t
|
||||
|
||||
-- XXX seems like we should be able to refute x is null here
|
||||
-- Assorted not-so-trivial refutation rules
|
||||
select * from test_predtest($$
|
||||
select x is null, x
|
||||
from booleans
|
||||
@ -207,8 +210,8 @@ $$);
|
||||
-[ RECORD 1 ]-----+--
|
||||
strong_implied_by | f
|
||||
weak_implied_by | f
|
||||
strong_refuted_by | f
|
||||
weak_refuted_by | f
|
||||
strong_refuted_by | t
|
||||
weak_refuted_by | t
|
||||
s_i_holds | f
|
||||
w_i_holds | f
|
||||
s_r_holds | t
|
||||
@ -222,12 +225,68 @@ $$);
|
||||
strong_implied_by | f
|
||||
weak_implied_by | f
|
||||
strong_refuted_by | f
|
||||
weak_refuted_by | f
|
||||
weak_refuted_by | t
|
||||
s_i_holds | f
|
||||
w_i_holds | t
|
||||
s_r_holds | f
|
||||
w_r_holds | t
|
||||
|
||||
select * from test_predtest($$
|
||||
select strictf(x,y), x is null
|
||||
from booleans
|
||||
$$);
|
||||
-[ RECORD 1 ]-----+--
|
||||
strong_implied_by | f
|
||||
weak_implied_by | f
|
||||
strong_refuted_by | f
|
||||
weak_refuted_by | t
|
||||
s_i_holds | f
|
||||
w_i_holds | t
|
||||
s_r_holds | f
|
||||
w_r_holds | t
|
||||
|
||||
select * from test_predtest($$
|
||||
select (x is not null) is not true, x
|
||||
from booleans
|
||||
$$);
|
||||
-[ RECORD 1 ]-----+--
|
||||
strong_implied_by | f
|
||||
weak_implied_by | f
|
||||
strong_refuted_by | t
|
||||
weak_refuted_by | t
|
||||
s_i_holds | f
|
||||
w_i_holds | f
|
||||
s_r_holds | t
|
||||
w_r_holds | t
|
||||
|
||||
select * from test_predtest($$
|
||||
select strictf(x,y), (x is not null) is false
|
||||
from booleans
|
||||
$$);
|
||||
-[ RECORD 1 ]-----+--
|
||||
strong_implied_by | f
|
||||
weak_implied_by | f
|
||||
strong_refuted_by | f
|
||||
weak_refuted_by | t
|
||||
s_i_holds | f
|
||||
w_i_holds | t
|
||||
s_r_holds | f
|
||||
w_r_holds | t
|
||||
|
||||
select * from test_predtest($$
|
||||
select x > y, (y < x) is false
|
||||
from integers
|
||||
$$);
|
||||
-[ RECORD 1 ]-----+--
|
||||
strong_implied_by | f
|
||||
weak_implied_by | f
|
||||
strong_refuted_by | t
|
||||
weak_refuted_by | t
|
||||
s_i_holds | f
|
||||
w_i_holds | f
|
||||
s_r_holds | t
|
||||
w_r_holds | t
|
||||
|
||||
-- Tests involving AND/OR constructs
|
||||
select * from test_predtest($$
|
||||
select x, x and y
|
||||
@ -369,6 +428,20 @@ w_i_holds | t
|
||||
s_r_holds | f
|
||||
w_r_holds | f
|
||||
|
||||
select * from test_predtest($$
|
||||
select x and z, x and y and z
|
||||
from booleans
|
||||
$$);
|
||||
-[ RECORD 1 ]-----+--
|
||||
strong_implied_by | t
|
||||
weak_implied_by | t
|
||||
strong_refuted_by | f
|
||||
weak_refuted_by | f
|
||||
s_i_holds | t
|
||||
w_i_holds | t
|
||||
s_r_holds | f
|
||||
w_r_holds | f
|
||||
|
||||
select * from test_predtest($$
|
||||
select z or w, x or y
|
||||
from booleans
|
||||
@ -644,7 +717,7 @@ $$);
|
||||
strong_implied_by | f
|
||||
weak_implied_by | f
|
||||
strong_refuted_by | t
|
||||
weak_refuted_by | f
|
||||
weak_refuted_by | t
|
||||
s_i_holds | f
|
||||
w_i_holds | f
|
||||
s_r_holds | t
|
||||
@ -658,7 +731,7 @@ $$);
|
||||
strong_implied_by | f
|
||||
weak_implied_by | f
|
||||
strong_refuted_by | t
|
||||
weak_refuted_by | f
|
||||
weak_refuted_by | t
|
||||
s_i_holds | f
|
||||
w_i_holds | f
|
||||
s_r_holds | t
|
||||
@ -708,7 +781,7 @@ w_i_holds | f
|
||||
s_r_holds | f
|
||||
w_r_holds | f
|
||||
|
||||
-- XXX ideally, we could prove this case too
|
||||
-- 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
|
||||
|
@ -21,6 +21,10 @@ select
|
||||
case (i/11)%11 when 10 then null else (i/11)%11 end as y
|
||||
from generate_series(0, 11*11-1) i;
|
||||
|
||||
-- and a simple strict function that's opaque to the optimizer
|
||||
create function strictf(bool, bool) returns bool
|
||||
language plpgsql as $$begin return $1 and not $2; end$$ strict;
|
||||
|
||||
-- Basic proof rules for single boolean variables
|
||||
|
||||
select * from test_predtest($$
|
||||
@ -88,7 +92,8 @@ select x, x is unknown
|
||||
from booleans
|
||||
$$);
|
||||
|
||||
-- XXX seems like we should be able to refute x is null here
|
||||
-- Assorted not-so-trivial refutation rules
|
||||
|
||||
select * from test_predtest($$
|
||||
select x is null, x
|
||||
from booleans
|
||||
@ -99,6 +104,26 @@ select x, x is null
|
||||
from booleans
|
||||
$$);
|
||||
|
||||
select * from test_predtest($$
|
||||
select strictf(x,y), x is null
|
||||
from booleans
|
||||
$$);
|
||||
|
||||
select * from test_predtest($$
|
||||
select (x is not null) is not true, x
|
||||
from booleans
|
||||
$$);
|
||||
|
||||
select * from test_predtest($$
|
||||
select strictf(x,y), (x is not null) is false
|
||||
from booleans
|
||||
$$);
|
||||
|
||||
select * from test_predtest($$
|
||||
select x > y, (y < x) is false
|
||||
from integers
|
||||
$$);
|
||||
|
||||
-- Tests involving AND/OR constructs
|
||||
|
||||
select * from test_predtest($$
|
||||
@ -151,6 +176,11 @@ select x or y or z, x or z
|
||||
from booleans
|
||||
$$);
|
||||
|
||||
select * from test_predtest($$
|
||||
select x and z, x and y and z
|
||||
from booleans
|
||||
$$);
|
||||
|
||||
select * from test_predtest($$
|
||||
select z or w, x or y
|
||||
from booleans
|
||||
@ -276,7 +306,7 @@ select x <= 5, x in (1,3,5,7)
|
||||
from integers
|
||||
$$);
|
||||
|
||||
-- XXX ideally, we could prove this case too
|
||||
-- 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
|
||||
|
@ -235,7 +235,7 @@ explain (costs off) select * from rlp where a = 1::bigint; /* same as above */
|
||||
Filter: (a = '1'::bigint)
|
||||
(3 rows)
|
||||
|
||||
explain (costs off) select * from rlp where a = 1::numeric; /* no pruning */
|
||||
explain (costs off) select * from rlp where a = 1::numeric; /* only null can be pruned */
|
||||
QUERY PLAN
|
||||
-----------------------------------------------
|
||||
Append
|
||||
@ -265,11 +265,9 @@ explain (costs off) select * from rlp where a = 1::numeric; /* no pruning */
|
||||
Filter: ((a)::numeric = '1'::numeric)
|
||||
-> Seq Scan on rlp_default_30
|
||||
Filter: ((a)::numeric = '1'::numeric)
|
||||
-> Seq Scan on rlp_default_null
|
||||
Filter: ((a)::numeric = '1'::numeric)
|
||||
-> Seq Scan on rlp_default_default
|
||||
Filter: ((a)::numeric = '1'::numeric)
|
||||
(31 rows)
|
||||
(29 rows)
|
||||
|
||||
explain (costs off) select * from rlp where a <= 10;
|
||||
QUERY PLAN
|
||||
|
@ -60,7 +60,7 @@ explain (costs off) select * from rlp where 1 > a; /* commuted */
|
||||
explain (costs off) select * from rlp where a <= 1;
|
||||
explain (costs off) select * from rlp where a = 1;
|
||||
explain (costs off) select * from rlp where a = 1::bigint; /* same as above */
|
||||
explain (costs off) select * from rlp where a = 1::numeric; /* no pruning */
|
||||
explain (costs off) select * from rlp where a = 1::numeric; /* only null can be pruned */
|
||||
explain (costs off) select * from rlp where a <= 10;
|
||||
explain (costs off) select * from rlp where a > 10;
|
||||
explain (costs off) select * from rlp where a < 15;
|
||||
|
Reference in New Issue
Block a user