diff options
author | Andres Freund <andres@anarazel.de> | 2015-07-24 11:48:53 +0200 |
---|---|---|
committer | Andres Freund <andres@anarazel.de> | 2015-07-24 11:52:22 +0200 |
commit | bb0203f26fa5f09fe2689a9db4bc632c1435edec (patch) | |
tree | c1dbfcf28c36c17b93d282058f6383a168a93429 /src/backend/parser/analyze.c | |
parent | fbf8dc21738749470f73f91a95ac01912c9deb10 (diff) | |
download | postgresql-bb0203f26fa5f09fe2689a9db4bc632c1435edec.tar.gz postgresql-bb0203f26fa5f09fe2689a9db4bc632c1435edec.zip |
Fix bug around assignment expressions containing indirections.
Handling of assigned-to expressions with indirection (e.g. set f1[1] =
3) was broken for ON CONFLICT DO UPDATE. The problem was that
ParseState was consulted to determine if an INSERT-appropriate or
UPDATE-appropriate behavior should be used when transforming expressions
with indirections. When the wrong path was taken the old row was
substituted with NULL, leading to wrong results..
To fix remove p_is_update and only use p_is_insert to decide how to
transform the assignment expression, and uset p_is_insert while parsing
the on conflict statement. This isn't particularly pretty, but it's not
any worse than before.
Author: Peter Geoghegan, slightly edited by me
Discussion: CAM3SWZS8RPvA=KFxADZWw3wAHnnbxMxDzkEC6fNaFc7zSm411w@mail.gmail.com
Backpatch: 9.5, where the feature was introduced
Diffstat (limited to 'src/backend/parser/analyze.c')
-rw-r--r-- | src/backend/parser/analyze.c | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index fc463faa6be..a0dfbf900a9 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -891,6 +891,12 @@ transformOnConflictClause(ParseState *pstate, /* Process DO UPDATE */ if (onConflictClause->action == ONCONFLICT_UPDATE) { + /* + * All INSERT expressions have been parsed, get ready for potentially + * existing SET statements that need to be processed like an UPDATE. + */ + pstate->p_is_insert = false; + exclRte = addRangeTableEntryForRelation(pstate, pstate->p_target_relation, makeAlias("excluded", NIL), @@ -1999,7 +2005,7 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt) Node *qual; qry->commandType = CMD_UPDATE; - pstate->p_is_update = true; + pstate->p_is_insert = false; /* process the WITH clause independently of all else */ if (stmt->withClause) |