mirror of
https://github.com/postgres/postgres.git
synced 2025-06-17 17:02:08 +03:00
Allow WITH clauses to be attached to INSERT, UPDATE, DELETE statements.
This is not the hoped-for facility of using INSERT/UPDATE/DELETE inside a WITH, but rather the other way around. It seems useful in its own right anyway. Note: catversion bumped because, although the contents of stored rules might look compatible, there's actually a subtle semantic change. A single Query containing a WITH and INSERT...VALUES now represents writing the WITH before the INSERT, not before the VALUES. While it's not clear that that matters to anyone, it seems like a good idea to have it cited in the git history for catversion.h. Original patch by Marko Tiikkaja, with updating and cleanup by Hitoshi Harada.
This commit is contained in:
@ -1867,6 +1867,35 @@ transformRuleStmt(RuleStmt *stmt, const char *queryString,
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* OLD/NEW are not allowed in WITH queries, because they would
|
||||
* amount to outer references for the WITH, which we disallow.
|
||||
* However, they were already in the outer rangetable when we
|
||||
* analyzed the query, so we have to check.
|
||||
*
|
||||
* Note that in the INSERT...SELECT case, we need to examine
|
||||
* the CTE lists of both top_subqry and sub_qry.
|
||||
*
|
||||
* Note that we aren't digging into the body of the query
|
||||
* looking for WITHs in nested sub-SELECTs. A WITH down there
|
||||
* can legitimately refer to OLD/NEW, because it'd be an
|
||||
* indirect-correlated outer reference.
|
||||
*/
|
||||
if (rangeTableEntry_used((Node *) top_subqry->cteList,
|
||||
PRS2_OLD_VARNO, 0) ||
|
||||
rangeTableEntry_used((Node *) sub_qry->cteList,
|
||||
PRS2_OLD_VARNO, 0))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("cannot refer to OLD within WITH query")));
|
||||
if (rangeTableEntry_used((Node *) top_subqry->cteList,
|
||||
PRS2_NEW_VARNO, 0) ||
|
||||
rangeTableEntry_used((Node *) sub_qry->cteList,
|
||||
PRS2_NEW_VARNO, 0))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("cannot refer to NEW within WITH query")));
|
||||
|
||||
/*
|
||||
* For efficiency's sake, add OLD to the rule action's jointree
|
||||
* only if it was actually referenced in the statement or qual.
|
||||
|
Reference in New Issue
Block a user