diff options
Diffstat (limited to 'src/backend/rewrite/rewriteManip.c')
-rw-r--r-- | src/backend/rewrite/rewriteManip.c | 85 |
1 files changed, 65 insertions, 20 deletions
diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c index 3e1f8f4a68d..02aa2d76653 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.51 2000/11/16 22:30:29 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.52 2000/12/05 19:15:09 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -472,6 +472,70 @@ attribute_used(Node *node, int rt_index, int attno, int sublevels_up) /* + * If the given Query is an INSERT ... SELECT construct, extract and + * return the sub-Query node that represents the SELECT part. Otherwise + * return the given Query. + * + * If subquery_ptr is not NULL, then *subquery_ptr is set to the location + * of the link to the SELECT subquery inside parsetree, or NULL if not an + * INSERT ... SELECT. + * + * This is a hack needed because transformations on INSERT ... SELECTs that + * appear in rule actions should be applied to the source SELECT, not to the + * INSERT part. Perhaps this can be cleaned up with redesigned querytrees. + */ +Query * +getInsertSelectQuery(Query *parsetree, Query ***subquery_ptr) +{ + Query *selectquery; + RangeTblEntry *selectrte; + RangeTblRef *rtr; + + if (subquery_ptr) + *subquery_ptr = NULL; + + if (parsetree == NULL) + return parsetree; + if (parsetree->commandType != CMD_INSERT) + return parsetree; + /* + * Currently, this is ONLY applied to rule-action queries, and so + * we expect to find the *OLD* and *NEW* placeholder entries in the + * given query. If they're not there, it must be an INSERT/SELECT + * in which they've been pushed down to the SELECT. + */ + if (length(parsetree->rtable) >= 2 && + strcmp(rt_fetch(PRS2_OLD_VARNO, parsetree->rtable)->eref->relname, + "*OLD*") == 0 && + strcmp(rt_fetch(PRS2_NEW_VARNO, parsetree->rtable)->eref->relname, + "*NEW*") == 0) + return parsetree; + Assert(parsetree->jointree && IsA(parsetree->jointree, FromExpr)); + if (length(parsetree->jointree->fromlist) != 1) + elog(ERROR, "getInsertSelectQuery: expected to find SELECT subquery"); + rtr = (RangeTblRef *) lfirst(parsetree->jointree->fromlist); + Assert(IsA(rtr, RangeTblRef)); + selectrte = rt_fetch(rtr->rtindex, parsetree->rtable); + selectquery = selectrte->subquery; + if (! (selectquery && IsA(selectquery, Query) && + selectquery->commandType == CMD_SELECT)) + elog(ERROR, "getInsertSelectQuery: expected to find SELECT subquery"); + if (length(selectquery->rtable) >= 2 && + strcmp(rt_fetch(PRS2_OLD_VARNO, selectquery->rtable)->eref->relname, + "*OLD*") == 0 && + strcmp(rt_fetch(PRS2_NEW_VARNO, selectquery->rtable)->eref->relname, + "*NEW*") == 0) + { + if (subquery_ptr) + *subquery_ptr = & (selectrte->subquery); + return selectquery; + } + elog(ERROR, "getInsertSelectQuery: can't find rule placeholders"); + return NULL; /* not reached */ +} + + +/* * Add the given qualifier condition to the query's WHERE clause */ void @@ -721,25 +785,6 @@ ResolveNew(Node *node, int target_varno, int sublevels_up, return ResolveNew_mutator(node, &context); } -/* - * Alternate interface to ResolveNew: substitute Vars in info->rule_action - * with targetlist items from the parsetree's targetlist. - */ -void -FixNew(RewriteInfo *info, Query *parsetree) -{ - ResolveNew_context context; - - context.target_varno = info->new_varno; - context.sublevels_up = 0; - context.targetlist = parsetree->targetList; - context.event = info->event; - context.update_varno = info->current_varno; - - query_tree_mutator(info->rule_action, ResolveNew_mutator, - (void *) &context, true); -} - #ifdef NOT_USED |