OSDN Git Service

Teach push_nots() how to negate a ScalarArrayOpExpr. In passing, save
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 26 Nov 2005 18:07:40 +0000 (18:07 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 26 Nov 2005 18:07:40 +0000 (18:07 +0000)
a palloc or two in the OpExpr case.

src/backend/optimizer/prep/prepqual.c

index 106d4d1..520e35f 100644 (file)
@@ -25,7 +25,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/prep/prepqual.c,v 1.52 2005/11/22 18:17:14 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/prep/prepqual.c,v 1.53 2005/11/26 18:07:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -212,11 +212,40 @@ push_nots(Expr *qual)
                Oid                     negator = get_negator(opexpr->opno);
 
                if (negator)
-                       return make_opclause(negator,
-                                                                opexpr->opresulttype,
-                                                                opexpr->opretset,
-                                                                (Expr *) get_leftop(qual),
-                                                                (Expr *) get_rightop(qual));
+               {
+                       OpExpr *newopexpr = makeNode(OpExpr);
+
+                       newopexpr->opno = negator;
+                       newopexpr->opfuncid = InvalidOid;
+                       newopexpr->opresulttype = opexpr->opresulttype;
+                       newopexpr->opretset = opexpr->opretset;
+                       newopexpr->args = opexpr->args;
+                       return (Expr *) newopexpr;
+               }
+               else
+                       return make_notclause(qual);
+       }
+       else if (qual && IsA(qual, ScalarArrayOpExpr))
+       {
+               /*
+                * Negate a ScalarArrayOpExpr if there is a negator for its operator;
+                * for example x = ANY (list) becomes x <> ALL (list).
+                * Otherwise, retain the clause as it is (the NOT can't be pushed down
+                * any farther).
+                */
+               ScalarArrayOpExpr *saopexpr = (ScalarArrayOpExpr *) qual;
+               Oid                     negator = get_negator(saopexpr->opno);
+
+               if (negator)
+               {
+                       ScalarArrayOpExpr *newopexpr = makeNode(ScalarArrayOpExpr);
+
+                       newopexpr->opno = negator;
+                       newopexpr->opfuncid = InvalidOid;
+                       newopexpr->useOr = !saopexpr->useOr;
+                       newopexpr->args = saopexpr->args;
+                       return (Expr *) newopexpr;
+               }
                else
                        return make_notclause(qual);
        }