mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03: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:
		@@ -896,7 +896,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
 | 
			
		||||
		{
 | 
			
		||||
			RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
 | 
			
		||||
			Node	   *childqual;
 | 
			
		||||
			bool		pseudoconstant;
 | 
			
		||||
			ListCell   *lc2;
 | 
			
		||||
 | 
			
		||||
			Assert(IsA(rinfo, RestrictInfo));
 | 
			
		||||
			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 */
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			/* check for pseudoconstant (no Vars or volatile functions) */
 | 
			
		||||
			pseudoconstant =
 | 
			
		||||
				!contain_vars_of_level(childqual, 0) &&
 | 
			
		||||
				!contain_volatile_functions(childqual);
 | 
			
		||||
			if (pseudoconstant)
 | 
			
		||||
			/* might have gotten an AND clause, if so flatten it */
 | 
			
		||||
			foreach(lc2, make_ands_implicit((Expr *) childqual))
 | 
			
		||||
			{
 | 
			
		||||
				/* tell createplan.c to check for gating quals */
 | 
			
		||||
				root->hasPseudoConstantQuals = true;
 | 
			
		||||
				Node	   *onecq = (Node *) lfirst(lc2);
 | 
			
		||||
				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 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 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);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user