]> granicus.if.org Git - postgresql/commitdiff
Fix Assert failure induced by commit 215b43cdc.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 19 Jan 2017 23:20:48 +0000 (18:20 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 19 Jan 2017 23:20:58 +0000 (18:20 -0500)
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

src/backend/optimizer/path/allpaths.c
src/test/regress/expected/union.out
src/test/regress/sql/union.sql

index 7c017fe1e4a707bd0f870018b1b51803f314978b..5c189874efa586230d115ab6181a6b17149b0ce0 100644 (file)
@@ -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);
                }
 
                /*
index d22db69c7d3dff118cdae63ead2683d8f605719d..4d697bada724d7fa93c13a6629d8e45476e711fe 100644 (file)
@@ -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)
+
index debd99ed51b8b83e627cbeed427d9f71cd1694c8..48e6850798e96a564c3d4ea6a2d4d37e4b514a30 100644 (file)
@@ -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);