aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/postgres_fdw/postgres_fdw.c8
-rw-r--r--src/backend/access/common/heaptuple.c2
-rw-r--r--src/backend/executor/execMain.c5
3 files changed, 12 insertions, 3 deletions
diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index 0c442608426..4f7123b84f4 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -2964,8 +2964,14 @@ make_tuple_from_result_row(PGresult *res,
tuple = heap_form_tuple(tupdesc, values, nulls);
+ /*
+ * If we have a CTID to return, install it in both t_self and t_ctid.
+ * t_self is the normal place, but if the tuple is converted to a
+ * composite Datum, t_self will be lost; setting t_ctid allows CTID to be
+ * preserved during EvalPlanQual re-evaluations (see ROW_MARK_COPY code).
+ */
if (ctid)
- tuple->t_self = *ctid;
+ tuple->t_self = tuple->t_data->t_ctid = *ctid;
/* Clean up */
MemoryContextReset(temp_context);
diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c
index 6cd4e8e11ae..f58f81e1ed7 100644
--- a/src/backend/access/common/heaptuple.c
+++ b/src/backend/access/common/heaptuple.c
@@ -727,6 +727,8 @@ heap_form_tuple(TupleDesc tupleDescriptor,
HeapTupleHeaderSetDatumLength(td, len);
HeapTupleHeaderSetTypeId(td, tupleDescriptor->tdtypeid);
HeapTupleHeaderSetTypMod(td, tupleDescriptor->tdtypmod);
+ /* We also make sure that t_ctid is invalid unless explicitly set */
+ ItemPointerSetInvalid(&(td->t_ctid));
HeapTupleHeaderSetNatts(td, numberOfAttributes);
td->t_hoff = hoff;
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 43d3c44c827..7c29b4b42ae 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -2613,10 +2613,11 @@ EvalPlanQualFetchRowMarks(EPQState *epqstate)
/* build a temporary HeapTuple control structure */
tuple.t_len = HeapTupleHeaderGetDatumLength(td);
- ItemPointerSetInvalid(&(tuple.t_self));
+ tuple.t_data = td;
/* relation might be a foreign table, if so provide tableoid */
tuple.t_tableOid = erm->relid;
- tuple.t_data = td;
+ /* also copy t_ctid in case there's valid data there */
+ tuple.t_self = td->t_ctid;
/* copy and store tuple */
EvalPlanQualSetTuple(epqstate, erm->rti,