Add defenses against trying to attach qual conditions to a setOperation
authorTom Lane
Wed, 16 Jul 2003 17:25:48 +0000 (17:25 +0000)
committerTom Lane
Wed, 16 Jul 2003 17:25:48 +0000 (17:25 +0000)
query node, since that won't work unless the planner is upgraded.
Someday we should try to support at least some cases of this, but for
now just plug the hole in the dike.  Per discussion with Dmitry Tkach.

src/backend/optimizer/prep/prepunion.c
src/backend/parser/analyze.c
src/backend/rewrite/rewriteHandler.c
src/backend/rewrite/rewriteManip.c

index 03674e8990f8088835267b187a7d7ff44cdaf85f..d14c3c98e1f3f47fd68d93e44fdc5bffb54517ba 100644 (file)
@@ -14,7 +14,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.97 2003/06/29 23:05:04 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.98 2003/07/16 17:25:48 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -85,6 +85,14 @@ plan_set_operations(Query *parse)
 
    Assert(topop && IsA(topop, SetOperationStmt));
 
+   /* check for unsupported stuff */
+   Assert(parse->utilityStmt == NULL);
+   Assert(parse->jointree->fromlist == NIL);
+   Assert(parse->jointree->quals == NULL);
+   Assert(parse->groupClause == NIL);
+   Assert(parse->havingQual == NULL);
+   Assert(parse->distinctClause == NIL);
+
    /*
     * Find the leftmost component Query.  We need to use its column names
     * for all generated tlists (else SELECT INTO won't work right).
index 90818b153b8376a0d6be32d8a4bf7a03b0b5610a..ca7759cfc8245040ecc1f41c22f1e178d43cded9 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.278 2003/07/03 19:07:30 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.279 2003/07/16 17:25:48 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1787,6 +1787,15 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt,
             */
            sub_qry = getInsertSelectQuery(top_subqry, NULL);
 
+           /*
+            * If the sub_qry is a setop, we cannot attach any qualifications
+            * to it, because the planner won't notice them.  This could
+            * perhaps be relaxed someday, but for now, we may as well reject
+            * such a rule immediately.
+            */
+           if (sub_qry->setOperations != NULL && stmt->whereClause != NULL)
+               elog(ERROR, "Conditional UNION/INTERSECT/EXCEPT statements are not implemented");
+
            /*
             * Validate action's use of OLD/NEW, qual too
             */
@@ -1841,6 +1850,13 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt,
             */
            if (has_old || (has_new && stmt->event == CMD_UPDATE))
            {
+               /*
+                * If sub_qry is a setop, manipulating its jointree will do
+                * no good at all, because the jointree is dummy.  (This
+                * should be a can't-happen case because of prior tests.)
+                */
+               if (sub_qry->setOperations != NULL)
+                   elog(ERROR, "Conditional UNION/INTERSECT/EXCEPT statements are not implemented");
                /* hack so we can use addRTEtoQuery() */
                sub_pstate->p_rtable = sub_qry->rtable;
                sub_pstate->p_joinlist = sub_qry->jointree->fromlist;
index a1d9122f828e9146974fa1571ed77e3dbc78078a..7ee28291e0d9e9ed58b7645fb67a12ff6d99f0f4 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.122 2003/07/03 16:34:25 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.123 2003/07/16 17:25:48 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -148,18 +148,31 @@ rewriteRuleAction(Query *parsetree,
     * As above, the action's jointree must not share substructure with the
     * main parsetree's.
     */
-   if (sub_action->jointree != NULL)
+   if (sub_action->commandType != CMD_UTILITY)
    {
        bool        keeporig;
        List       *newjointree;
 
+       Assert(sub_action->jointree != NULL);
        keeporig = (!rangeTableEntry_used((Node *) sub_action->jointree,
                                          rt_index, 0)) &&
            (rangeTableEntry_used(rule_qual, rt_index, 0) ||
          rangeTableEntry_used(parsetree->jointree->quals, rt_index, 0));
        newjointree = adjustJoinTreeList(parsetree, !keeporig, rt_index);
-       sub_action->jointree->fromlist =
-           nconc(newjointree, sub_action->jointree->fromlist);
+       if (newjointree != NIL)
+       {
+           /*
+            * If sub_action is a setop, manipulating its jointree will do
+            * no good at all, because the jointree is dummy.  (Perhaps
+            * someday we could push the joining and quals down to the
+            * member statements of the setop?)
+            */
+           if (sub_action->setOperations != NULL)
+               elog(ERROR, "Conditional UNION/INTERSECT/EXCEPT statements are not implemented");
+
+           sub_action->jointree->fromlist =
+               nconc(newjointree, sub_action->jointree->fromlist);
+       }
    }
 
    /*
index 0d3dbe7d6e6b9ecc43e4fed0929cd9d098f400d8..1cd42a44f76fccd3125eb3168fb696d7cda5264f 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.72 2003/06/06 15:04:02 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.73 2003/07/16 17:25:48 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -733,6 +733,16 @@ AddQual(Query *parsetree, Node *qual)
            elog(ERROR, "Conditional utility statements are not implemented");
    }
 
+   if (parsetree->setOperations != NULL)
+   {
+       /*
+        * There's noplace to put the qual on a setop statement, either.
+        * (This could be fixed, but right now the planner simply ignores
+        * any qual condition on a setop query.)
+        */
+       elog(ERROR, "Conditional UNION/INTERSECT/EXCEPT statements are not implemented");
+   }
+
    /* INTERSECT want's the original, but we need to copy - Jan */
    copy = copyObject(qual);
 
@@ -773,6 +783,16 @@ AddHavingQual(Query *parsetree, Node *havingQual)
            elog(ERROR, "Conditional utility statements are not implemented");
    }
 
+   if (parsetree->setOperations != NULL)
+   {
+       /*
+        * There's noplace to put the qual on a setop statement, either.
+        * (This could be fixed, but right now the planner simply ignores
+        * any qual condition on a setop query.)
+        */
+       elog(ERROR, "Conditional UNION/INTERSECT/EXCEPT statements are not implemented");
+   }
+
    /* INTERSECT want's the original, but we need to copy - Jan */
    copy = copyObject(havingQual);