diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2012-08-19 14:12:16 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2012-08-19 14:12:16 -0400 |
commit | 092d7ded29f36b0539046b23b81b9f0bf2d637f1 (patch) | |
tree | 9d42dc496cf768b95fafd903f01bb9ee9dbd9b73 /src/backend/parser/analyze.c | |
parent | c246eb5aafe66d5537b468d6da2116c462775faf (diff) |
Allow OLD and NEW in multi-row VALUES within rules.
Now that we have LATERAL, it's fairly painless to allow this case, which
was left as a TODO in the original multi-row VALUES implementation.
Diffstat (limited to 'src/backend/parser/analyze.c')
-rw-r--r-- | src/backend/parser/analyze.c | 46 |
1 files changed, 19 insertions, 27 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 6c3d89a14f6..823d3b445a7 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -587,6 +587,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt) List *exprsLists = NIL; List *collations = NIL; int sublist_length = -1; + bool lateral = false; int i; Assert(selectStmt->intoClause == NULL); @@ -647,25 +648,20 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt) collations = lappend_oid(collations, InvalidOid); /* - * Another thing we can't currently support is NEW/OLD references in - * rules --- seems we'd need something like SQL99's LATERAL construct - * to ensure that the values would be available while evaluating the - * VALUES RTE. This is a shame. FIXME + * Ordinarily there can't be any current-level Vars in the expression + * lists, because the namespace was empty ... but if we're inside + * CREATE RULE, then NEW/OLD references might appear. In that case we + * have to mark the VALUES RTE as LATERAL. */ if (list_length(pstate->p_rtable) != 1 && contain_vars_of_level((Node *) exprsLists, 0)) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("VALUES must not contain OLD or NEW references"), - errhint("Use SELECT ... UNION ALL ... instead."), - parser_errposition(pstate, - locate_var_of_level((Node *) exprsLists, 0)))); + lateral = true; /* * Generate the VALUES RTE */ rte = addRangeTableEntryForValues(pstate, exprsLists, collations, - NULL, true); + NULL, lateral, true); rtr = makeNode(RangeTblRef); /* assume new rte is at end */ rtr->rtindex = list_length(pstate->p_rtable); @@ -1032,6 +1028,7 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt) List *collations; List **colexprs = NULL; int sublist_length = -1; + bool lateral = false; RangeTblEntry *rte; int rtindex; ListCell *lc; @@ -1177,10 +1174,20 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt) } /* + * Ordinarily there can't be any current-level Vars in the expression + * lists, because the namespace was empty ... but if we're inside CREATE + * RULE, then NEW/OLD references might appear. In that case we have to + * mark the VALUES RTE as LATERAL. + */ + if (pstate->p_rtable != NIL && + contain_vars_of_level((Node *) exprsLists, 0)) + lateral = true; + + /* * Generate the VALUES RTE */ rte = addRangeTableEntryForValues(pstate, exprsLists, collations, - NULL, true); + NULL, lateral, true); addRTEtoQuery(pstate, rte, true, true, true); /* assume new rte is at end */ @@ -1214,21 +1221,6 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt) (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("SELECT FOR UPDATE/SHARE cannot be applied to VALUES"))); - /* - * Another thing we can't currently support is NEW/OLD references in rules - * --- seems we'd need something like SQL99's LATERAL construct to ensure - * that the values would be available while evaluating the VALUES RTE. - * This is a shame. FIXME - */ - if (list_length(pstate->p_rtable) != 1 && - contain_vars_of_level((Node *) exprsLists, 0)) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("VALUES must not contain OLD or NEW references"), - errhint("Use SELECT ... UNION ALL ... instead."), - parser_errposition(pstate, - locate_var_of_level((Node *) exprsLists, 0)))); - qry->rtable = pstate->p_rtable; qry->jointree = makeFromExpr(pstate->p_joinlist, NULL); |