summaryrefslogtreecommitdiff
path: root/src/backend/parser/analyze.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2012-08-19 14:12:16 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2012-08-19 14:12:16 -0400
commit092d7ded29f36b0539046b23b81b9f0bf2d637f1 (patch)
tree9d42dc496cf768b95fafd903f01bb9ee9dbd9b73 /src/backend/parser/analyze.c
parentc246eb5aafe66d5537b468d6da2116c462775faf (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.c46
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);