]> granicus.if.org Git - postgresql/commitdiff
Fix make_restrictinfo_from_bitmapqual() to preserve AND/OR flatness of its
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 7 Apr 2006 17:05:39 +0000 (17:05 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 7 Apr 2006 17:05:39 +0000 (17:05 +0000)
output, ie, no OR immediately below an OR.  Otherwise we get Asserts or
wrong answers for cases such as
select * from tenk1 a, tenk1 b
where (a.ten = b.ten and (a.unique1 = 100 or a.unique1 = 101))
   or (a.hundred = b.hundred and a.unique1 = 42);
Per report from Rafael Martinez Guerrero.

src/backend/optimizer/util/restrictinfo.c

index ec7e488b48b86d88f1260fd0d919e32e00b28984..606f77bf90018822d9b3135e3a8ad085b3d1915b 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.46 2006/03/05 15:58:32 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.47 2006/04/07 17:05:39 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -160,13 +160,44 @@ make_restrictinfo_from_bitmapqual(Path *bitmapqual,
                                 */
                                return NIL;
                        }
-                       /* Create AND subclause with RestrictInfos */
-                       withris = lappend(withris,
-                                                         make_ands_explicit(sublist));
-                       /* And one without */
-                       sublist = get_actual_clauses(sublist);
-                       withoutris = lappend(withoutris,
-                                                                make_ands_explicit(sublist));
+                       /*
+                        * If the sublist contains multiple RestrictInfos, we create an
+                        * AND subclause.  If there's just one, we have to check if it's
+                        * an OR clause, and if so flatten it to preserve AND/OR flatness
+                        * of our output.
+                        *
+                        * We construct lists with and without sub-RestrictInfos, so
+                        * as not to have to regenerate duplicate RestrictInfos below.
+                        */
+                       if (list_length(sublist) > 1)
+                       {
+                               withris = lappend(withris, make_andclause(sublist));
+                               sublist = get_actual_clauses(sublist);
+                               withoutris = lappend(withoutris, make_andclause(sublist));
+                       }
+                       else
+                       {
+                               RestrictInfo   *subri = (RestrictInfo *) linitial(sublist);
+
+                               Assert(IsA(subri, RestrictInfo));
+                               if (restriction_is_or_clause(subri))
+                               {
+                                       BoolExpr   *subor = (BoolExpr *) subri->orclause;
+
+                                       Assert(or_clause((Node *) subor));
+                                       withris = list_concat(withris,
+                                                                                 list_copy(subor->args));
+                                       subor = (BoolExpr *) subri->clause;
+                                       Assert(or_clause((Node *) subor));
+                                       withoutris = list_concat(withoutris,
+                                                                                        list_copy(subor->args));
+                               }
+                               else
+                               {
+                                       withris = lappend(withris, subri);
+                                       withoutris = lappend(withoutris, subri->clause);
+                               }
+                       }
                }
 
                /*