Add defenses against trying to attach qual conditions to a setOperation
authorTom Lane <[email protected]>
Wed, 16 Jul 2003 17:25:48 +0000 (17:25 +0000)
committerTom Lane <[email protected]>
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 8d91a964011d324a97adb5958ff5edbece9454f3..deec293b8b30086b6b4f72ca434b3a5ae9275116 100644 (file)
@@ -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 12023ee0828b55b14639abef14104722297c019b..e3c38e1367756407badd602e1bb950acffebfbb7 100644 (file)
@@ -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 f4ca111fda54dd042ab69112d2e047a5bb727711..bd4ffb4c37f06a13928335540834f8164c65a879 100644 (file)
@@ -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 7ab12e76d7171180609061210b6c81b432f6a227..5bd66162c5ea59f73b82b03e6b9284b1e5fef285 100644 (file)
@@ -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);