diff options
author | Andres Freund <andres@anarazel.de> | 2019-07-24 18:45:58 -0700 |
---|---|---|
committer | Andres Freund <andres@anarazel.de> | 2019-07-24 18:45:58 -0700 |
commit | ecbdd009344d3a00733e4382f50137b5e0248ce8 (patch) | |
tree | 38b235602ba439d9f6b9802827e9db135569ecfb /src/backend/executor/nodeModifyTable.c | |
parent | c8e177f0bba6bcd9db7180580d58968974d8f6a9 (diff) | |
download | postgresql-ecbdd009344d3a00733e4382f50137b5e0248ce8.tar.gz postgresql-ecbdd009344d3a00733e4382f50137b5e0248ce8.zip |
Fix system column accesses in ON CONFLICT ... RETURNING.
After 277cb789836 ON CONFLICT ... SET ... RETURNING failed with
ERROR: virtual tuple table slot does not have system attributes
when taking the update path, as the slot used to insert into the
table (and then process RETURNING) was defined to be a virtual slot in
that commit. Virtual slots don't support system columns except for
tableoid and ctid, as the other system columns are AM dependent.
Fix that by using a slot of the table's type. Add tests for system
column accesses in ON CONFLICT ... RETURNING.
Reported-By: Roby, bisected to the relevant commit by Jeff Janes
Author: Andres Freund
Discussion: https://postgr.es/m/73436355-6432-49B1-92ED-1FE4F7E7E100@finefun.com.au
Backpatch: 12-, where the bug was introduced in 277cb789836
Diffstat (limited to 'src/backend/executor/nodeModifyTable.c')
-rw-r--r-- | src/backend/executor/nodeModifyTable.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c index d8b695d897f..9e0c8794c40 100644 --- a/src/backend/executor/nodeModifyTable.c +++ b/src/backend/executor/nodeModifyTable.c @@ -2542,11 +2542,16 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) table_slot_create(resultRelInfo->ri_RelationDesc, &mtstate->ps.state->es_tupleTable); - /* create the tuple slot for the UPDATE SET projection */ + /* + * Create the tuple slot for the UPDATE SET projection. We want a slot + * of the table's type here, because the slot will be used to insert + * into the table, and for RETURNING processing - which may access + * system attributes. + */ tupDesc = ExecTypeFromTL((List *) node->onConflictSet); resultRelInfo->ri_onConflict->oc_ProjSlot = ExecInitExtraTupleSlot(mtstate->ps.state, tupDesc, - &TTSOpsVirtual); + table_slot_callbacks(resultRelInfo->ri_RelationDesc)); /* build UPDATE SET projection state */ resultRelInfo->ri_onConflict->oc_ProjInfo = |