diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c index 03674e8990..d14c3c98e1 100644 --- a/src/backend/optimizer/prep/prepunion.c +++ b/src/backend/optimizer/prep/prepunion.c @@ -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). diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 90818b153b..ca7759cfc8 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -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; diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c index a1d9122f82..7ee28291e0 100644 --- a/src/backend/rewrite/rewriteHandler.c +++ b/src/backend/rewrite/rewriteHandler.c @@ -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); + } } /* diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c index 0d3dbe7d6e..1cd42a44f7 100644 --- a/src/backend/rewrite/rewriteManip.c +++ b/src/backend/rewrite/rewriteManip.c @@ -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);