aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/heap/heapam.c11
-rw-r--r--src/backend/access/heap/rewriteheap.c19
-rw-r--r--src/backend/replication/logical/reorderbuffer.c25
-rw-r--r--src/include/access/heapam.h1
4 files changed, 47 insertions, 9 deletions
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 44d150f706f..c7dd2be6fc1 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -2378,6 +2378,11 @@ ReleaseBulkInsertStatePin(BulkInsertState bistate)
* Speculatively inserted tuples behave as "value locks" of short duration,
* used to implement INSERT .. ON CONFLICT.
*
+ * HEAP_INSERT_NO_LOGICAL force-disables the emitting of logical decoding
+ * information for the tuple. This should solely be used during table rewrites
+ * where RelationIsLogicallyLogged(relation) is not yet accurate for the new
+ * relation.
+ *
* Note that most of these options will be applied when inserting into the
* heap's TOAST table, too, if the tuple requires any out-of-line data. Only
* HEAP_INSERT_IS_SPECULATIVE is explicitly ignored, as the toast data does
@@ -2506,7 +2511,8 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
* page write, so make sure it's included even if we take a full-page
* image. (XXX We could alternatively store a pointer into the FPW).
*/
- if (RelationIsLogicallyLogged(relation))
+ if (RelationIsLogicallyLogged(relation) &&
+ !(options & HEAP_INSERT_NO_LOGICAL))
{
xlrec.flags |= XLH_INSERT_CONTAINS_NEW_TUPLE;
bufflags |= REGBUF_KEEP_DATA;
@@ -2669,6 +2675,9 @@ heap_multi_insert(Relation relation, HeapTuple *tuples, int ntuples,
bool need_tuple_data = RelationIsLogicallyLogged(relation);
bool need_cids = RelationIsAccessibleInLogicalDecoding(relation);
+ /* currently not needed (thus unsupported) for heap_multi_insert() */
+ AssertArg(!(options & HEAP_INSERT_NO_LOGICAL));
+
needwal = !(options & HEAP_INSERT_SKIP_WAL) && RelationNeedsWAL(relation);
saveFreeSpace = RelationGetTargetPageFreeSpace(relation,
HEAP_DEFAULT_FILLFACTOR);
diff --git a/src/backend/access/heap/rewriteheap.c b/src/backend/access/heap/rewriteheap.c
index b30fcba726c..09b21c927cb 100644
--- a/src/backend/access/heap/rewriteheap.c
+++ b/src/backend/access/heap/rewriteheap.c
@@ -651,10 +651,23 @@ raw_heap_insert(RewriteState state, HeapTuple tup)
heaptup = tup;
}
else if (HeapTupleHasExternal(tup) || tup->t_len > TOAST_TUPLE_THRESHOLD)
+ {
+ int options = HEAP_INSERT_SKIP_FSM;
+
+ if (!state->rs_use_wal)
+ options |= HEAP_INSERT_SKIP_WAL;
+
+ /*
+ * The new relfilenode's relcache entrye doesn't have the necessary
+ * information to determine whether a relation should emit data for
+ * logical decoding. Force it to off if necessary.
+ */
+ if (!RelationIsLogicallyLogged(state->rs_old_rel))
+ options |= HEAP_INSERT_NO_LOGICAL;
+
heaptup = toast_insert_or_update(state->rs_new_rel, tup, NULL,
- HEAP_INSERT_SKIP_FSM |
- (state->rs_use_wal ?
- 0 : HEAP_INSERT_SKIP_WAL));
+ options);
+ }
else
heaptup = tup;
diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c
index d55abb8c34f..e09fc9511be 100644
--- a/src/backend/replication/logical/reorderbuffer.c
+++ b/src/backend/replication/logical/reorderbuffer.c
@@ -1535,8 +1535,16 @@ ReorderBufferCommit(ReorderBuffer *rb, TransactionId xid,
change->data.tp.relnode.relNode);
/*
- * Catalog tuple without data, emitted while catalog was
- * in the process of being rewritten.
+ * Mapped catalog tuple without data, emitted while
+ * catalog table was in the process of being rewritten. We
+ * can fail to look up the relfilenode, because the the
+ * relmapper has no "historic" view, in contrast to normal
+ * the normal catalog during decoding. Thus repeated
+ * rewrites can cause a lookup failure. That's OK because
+ * we do not decode catalog changes anyway. Normally such
+ * tuples would be skipped over below, but we can't
+ * identify whether the table should be logically logged
+ * without mapping the relfilenode to the oid.
*/
if (reloid == InvalidOid &&
change->data.tp.newtuple == NULL &&
@@ -1591,10 +1599,17 @@ ReorderBufferCommit(ReorderBuffer *rb, TransactionId xid,
* transaction's changes. Otherwise it will get
* freed/reused while restoring spooled data from
* disk.
+ *
+ * But skip doing so if there's no tuple-data. That
+ * happens if a non-mapped system catalog with a toast
+ * table is rewritten.
*/
- dlist_delete(&change->node);
- ReorderBufferToastAppendChunk(rb, txn, relation,
- change);
+ if (change->data.tp.newtuple != NULL)
+ {
+ dlist_delete(&change->node);
+ ReorderBufferToastAppendChunk(rb, txn, relation,
+ change);
+ }
}
change_done:
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index f1366ed9581..051994d22af 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -29,6 +29,7 @@
#define HEAP_INSERT_SKIP_FSM 0x0002
#define HEAP_INSERT_FROZEN 0x0004
#define HEAP_INSERT_SPECULATIVE 0x0008
+#define HEAP_INSERT_NO_LOGICAL 0x0010
typedef struct BulkInsertStateData *BulkInsertState;