mirror of
https://github.com/postgres/postgres.git
synced 2025-05-31 00:01:57 -04:00
Fix Assert failure induced by commit 215b43cdc.
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
This commit is contained in:
parent
182200531a
commit
d479e37e3d
@ -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,
|
|||||||
/* 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
|
|||||||
|
|
||||||
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
|
|||||||
|
|
||||||
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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user