Commit d479e37e authored by Tom Lane's avatar Tom Lane

Fix Assert failure induced by commit 215b43cd.

I'd somehow talked myself into believing that set_append_rel_size
doesn't need to worry about getting back an AND clause when it applies
eval_const_expressions to the result of adjust_appendrel_attrs (that is,
transposing the appendrel parent's restriction clauses for one child).
But that is nonsense, and Andreas Seltenreich's fuzz tester soon
turned up a counterexample.  Put back the make_ands_implicit step
that was there before, and add a regression test covering the case.

Report: https://postgr.es/m/878tq6vja6.fsf@ansel.ydns.eu
parent 18220053
...@@ -896,7 +896,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, ...@@ -896,7 +896,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
{ {
RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc); RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
Node *childqual; Node *childqual;
bool pseudoconstant; ListCell *lc2;
Assert(IsA(rinfo, RestrictInfo)); Assert(IsA(rinfo, RestrictInfo));
childqual = adjust_appendrel_attrs(root, childqual = adjust_appendrel_attrs(root,
...@@ -916,25 +916,32 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, ...@@ -916,25 +916,32 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
/* Restriction reduces to constant TRUE, so drop it */ /* Restriction reduces to constant TRUE, so drop it */
continue; continue;
} }
/* check for pseudoconstant (no Vars or volatile functions) */ /* might have gotten an AND clause, if so flatten it */
pseudoconstant = foreach(lc2, make_ands_implicit((Expr *) childqual))
!contain_vars_of_level(childqual, 0) &&
!contain_volatile_functions(childqual);
if (pseudoconstant)
{ {
/* tell createplan.c to check for gating quals */ Node *onecq = (Node *) lfirst(lc2);
root->hasPseudoConstantQuals = true; bool pseudoconstant;
/* check for pseudoconstant (no Vars or volatile functions) */
pseudoconstant =
!contain_vars_of_level(onecq, 0) &&
!contain_volatile_functions(onecq);
if (pseudoconstant)
{
/* tell createplan.c to check for gating quals */
root->hasPseudoConstantQuals = true;
}
/* reconstitute RestrictInfo with appropriate properties */
childquals = lappend(childquals,
make_restrictinfo((Expr *) onecq,
rinfo->is_pushed_down,
rinfo->outerjoin_delayed,
pseudoconstant,
rinfo->security_level,
NULL, NULL, NULL));
/* track minimum security level among child quals */
cq_min_security = Min(cq_min_security, rinfo->security_level);
} }
/* reconstitute RestrictInfo with appropriate properties */
childquals = lappend(childquals,
make_restrictinfo((Expr *) childqual,
rinfo->is_pushed_down,
rinfo->outerjoin_delayed,
pseudoconstant,
rinfo->security_level,
NULL, NULL, NULL));
/* track minimum security level among child quals */
cq_min_security = Min(cq_min_security, rinfo->security_level);
} }
/* /*
......
...@@ -720,3 +720,33 @@ select * from ...@@ -720,3 +720,33 @@ select * from
drop table t3; drop table t3;
drop function expensivefunc(int); drop function expensivefunc(int);
-- Test handling of appendrel quals that const-simplify into an AND
explain (costs off)
select * from
(select *, 0 as x from int8_tbl a
union all
select *, 1 as x from int8_tbl b) ss
where (x = 0) or (q1 >= q2 and q1 <= q2);
QUERY PLAN
---------------------------------------------
Append
-> Seq Scan on int8_tbl a
-> Seq Scan on int8_tbl b
Filter: ((q1 >= q2) AND (q1 <= q2))
(4 rows)
select * from
(select *, 0 as x from int8_tbl a
union all
select *, 1 as x from int8_tbl b) ss
where (x = 0) or (q1 >= q2 and q1 <= q2);
q1 | q2 | x
------------------+-------------------+---
123 | 456 | 0
123 | 4567890123456789 | 0
4567890123456789 | 123 | 0
4567890123456789 | 4567890123456789 | 0
4567890123456789 | -4567890123456789 | 0
4567890123456789 | 4567890123456789 | 1
(6 rows)
...@@ -322,3 +322,16 @@ select * from ...@@ -322,3 +322,16 @@ select * from
drop table t3; drop table t3;
drop function expensivefunc(int); drop function expensivefunc(int);
-- Test handling of appendrel quals that const-simplify into an AND
explain (costs off)
select * from
(select *, 0 as x from int8_tbl a
union all
select *, 1 as x from int8_tbl b) ss
where (x = 0) or (q1 >= q2 and q1 <= q2);
select * from
(select *, 0 as x from int8_tbl a
union all
select *, 1 as x from int8_tbl b) ss
where (x = 0) or (q1 >= q2 and q1 <= q2);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment