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);
+               }
+           }
        }
 
        /*