* RewriteQuery - * rewrites the query and apply the rules again on the queries rewritten * * rewrite_events is a list of open query-rewrite actions, so we can detect * infinite recursion. */
| 3663 | * infinite recursion. |
| 3664 | */ |
| 3665 | static List * |
| 3666 | RewriteQuery(Query *parsetree, List *rewrite_events) |
| 3667 | { |
| 3668 | CmdType event = parsetree->commandType; |
| 3669 | bool instead = false; |
| 3670 | bool returning = false; |
| 3671 | bool updatableview = false; |
| 3672 | Query *qual_product = NULL; |
| 3673 | List *rewritten = NIL; |
| 3674 | ListCell *lc1; |
| 3675 | |
| 3676 | /* |
| 3677 | * First, recursively process any insert/update/delete statements in WITH |
| 3678 | * clauses. (We have to do this first because the WITH clauses may get |
| 3679 | * copied into rule actions below.) |
| 3680 | */ |
| 3681 | foreach(lc1, parsetree->cteList) |
| 3682 | { |
| 3683 | CommonTableExpr *cte = lfirst_node(CommonTableExpr, lc1); |
| 3684 | Query *ctequery = castNode(Query, cte->ctequery); |
| 3685 | List *newstuff; |
| 3686 | |
| 3687 | if (ctequery->commandType == CMD_SELECT) |
| 3688 | continue; |
| 3689 | |
| 3690 | newstuff = RewriteQuery(ctequery, rewrite_events); |
| 3691 | |
| 3692 | /* |
| 3693 | * Currently we can only handle unconditional, single-statement DO |
| 3694 | * INSTEAD rules correctly; we have to get exactly one non-utility |
| 3695 | * Query out of the rewrite operation to stuff back into the CTE node. |
| 3696 | */ |
| 3697 | if (list_length(newstuff) == 1) |
| 3698 | { |
| 3699 | /* Must check it's not a utility command */ |
| 3700 | ctequery = linitial_node(Query, newstuff); |
| 3701 | if (!(ctequery->commandType == CMD_SELECT || |
| 3702 | ctequery->commandType == CMD_UPDATE || |
| 3703 | ctequery->commandType == CMD_INSERT || |
| 3704 | ctequery->commandType == CMD_DELETE)) |
| 3705 | { |
| 3706 | /* |
| 3707 | * Currently it could only be NOTIFY; this error message will |
| 3708 | * need work if we ever allow other utility commands in rules. |
| 3709 | */ |
| 3710 | ereport(ERROR, |
| 3711 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| 3712 | errmsg("DO INSTEAD NOTIFY rules are not supported for data-modifying statements in WITH"))); |
| 3713 | } |
| 3714 | /* WITH queries should never be canSetTag */ |
| 3715 | Assert(!ctequery->canSetTag); |
| 3716 | /* Push the single Query back into the CTE node */ |
| 3717 | cte->ctequery = (Node *) ctequery; |
| 3718 | } |
| 3719 | else if (newstuff == NIL) |
| 3720 | { |
| 3721 | ereport(ERROR, |
| 3722 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
no test coverage detected