Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
199 changes: 199 additions & 0 deletions patches/19/pg19-015-attoptions.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index 50747c16396..6cdbbe1d0dd 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -166,6 +166,15 @@ static relopt_bool boolRelOpts[] =
},
true
},
+ {
+ {
+ "log_old_value",
+ "Add old value of attribute to WAL for logical decoding",
+ RELOPT_KIND_ATTRIBUTE,
+ ShareUpdateExclusiveLock
+ },
+ false
+ },
/* list terminator */
{{NULL}}
};
@@ -557,6 +566,19 @@ static relopt_enum enumRelOpts[] =

static relopt_string stringRelOpts[] =
{
+ {
+ {
+ "delta_apply_function",
+ "Function called to perform delta conflict avoidance",
+ RELOPT_KIND_ATTRIBUTE,
+ ShareUpdateExclusiveLock
+ },
+ -1,
+ true,
+ NULL,
+ NULL,
+ NULL
+ },
/* list terminator */
{{NULL}}
};
@@ -2106,7 +2128,9 @@ attribute_reloptions(Datum reloptions, bool validate)
{
static const relopt_parse_elt tab[] = {
{"n_distinct", RELOPT_TYPE_REAL, offsetof(AttributeOpts, n_distinct)},
- {"n_distinct_inherited", RELOPT_TYPE_REAL, offsetof(AttributeOpts, n_distinct_inherited)}
+ {"n_distinct_inherited", RELOPT_TYPE_REAL, offsetof(AttributeOpts, n_distinct_inherited)},
+ {"log_old_value", RELOPT_TYPE_BOOL, offsetof(AttributeOpts, log_old_value)},
+ {"delta_apply_function", RELOPT_TYPE_STRING, offsetof(AttributeOpts, delta_apply_function)}
};

return (bytea *) build_reloptions(reloptions, validate,
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 0dcd6ee817e..dcf26167cae 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -52,4 +52,5 @@
#include "storage/procarray.h"
+#include "utils/attoptcache.h"
#include "utils/datum.h"
#include "utils/injection_point.h"
#include "utils/inval.h"
@@ -67,6 +68,7 @@ static void check_lock_if_inplace_updateable_rel(Relation relation,
HeapTuple newtup);
static void check_inplace_rel_lock(HeapTuple oldtup);
#endif
+static Bitmapset *HeapDetermineLogOldColumns(Relation relation);
static Bitmapset *HeapDetermineColumnsInfo(Relation relation,
Bitmapset *interesting_cols,
Bitmapset *external_cols,
@@ -104,6 +106,7 @@ static void index_delete_sort(TM_IndexDeleteOp *delstate);
static int bottomup_sort_and_shrink(TM_IndexDeleteOp *delstate);
static XLogRecPtr log_heap_new_cid(Relation relation, HeapTuple tup);
static HeapTuple ExtractReplicaIdentity(Relation relation, HeapTuple tp, bool key_required,
+ Bitmapset *logged_old_attrs,
bool *copy);


@@ -3016,8 +3019,8 @@ l1:
* Compute replica identity tuple before entering the critical section so
* we don't PANIC upon a memory allocation failure.
*/
- old_key_tuple = walLogical ?
- ExtractReplicaIdentity(relation, &tp, true, &old_key_copied) : NULL;
+ old_key_tuple = walLogical ?
+ ExtractReplicaIdentity(relation, &tp, true, NULL, &old_key_copied) : NULL;

/*
* If this is the first possibly-multixact-able operation in the current
@@ -3249,6 +3252,7 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
Bitmapset *id_attrs;
Bitmapset *interesting_attrs;
Bitmapset *modified_attrs;
+ Bitmapset *logged_old_attrs;
ItemId lp;
HeapTupleData oldtup;
HeapTuple heaptup;
@@ -3419,6 +3423,12 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
id_attrs, &oldtup,
newtup, &id_has_external);

+ if (!IsCatalogRelationOid(relation->rd_id))
+ logged_old_attrs = HeapDetermineLogOldColumns(relation);
+ else
+ /* No need to log old values for catalog tables */
+ logged_old_attrs = NULL;
+
/*
* If we're not updating any "key" column, we can grab a weaker lock type.
* This allows for more concurrency when we are running simultaneously
@@ -3692,6 +3702,7 @@ l2:
bms_free(key_attrs);
bms_free(id_attrs);
bms_free(modified_attrs);
+ bms_free(logged_old_attrs);
bms_free(interesting_attrs);
return result;
}
@@ -4041,6 +4052,7 @@ l2:
old_key_tuple = ExtractReplicaIdentity(relation, &oldtup,
bms_overlap(modified_attrs, id_attrs) ||
id_has_external,
+ logged_old_attrs,
&old_key_copied);

/* NO EREPORT(ERROR) from here till changes are logged */
@@ -4207,6 +4219,7 @@ l2:
bms_free(key_attrs);
bms_free(id_attrs);
bms_free(modified_attrs);
+ bms_free(logged_old_attrs);
bms_free(interesting_attrs);

return TM_Ok;
@@ -4379,6 +4392,26 @@ heap_attr_equals(TupleDesc tupdesc, int attrnum, Datum value1, Datum value2,
}
}

+static Bitmapset *
+HeapDetermineLogOldColumns(Relation relation)
+{
+ int attnum;
+ Bitmapset *logged_cols = NULL;
+ TupleDesc tupdesc = RelationGetDescr(relation);
+ AttributeOpts *aopt;
+
+ for (attnum = 1; attnum <= tupdesc->natts; attnum++)
+ {
+ aopt = get_attribute_options(relation->rd_id, attnum);
+ if (aopt != NULL && aopt->log_old_value)
+ logged_cols = bms_add_member(logged_cols,
+ attnum -
+ FirstLowInvalidHeapAttributeNumber);
+ }
+
+ return logged_cols;
+}
+
/*
* Check which columns are being updated.
*
@@ -9132,6 +9165,7 @@ log_heap_new_cid(Relation relation, HeapTuple tup)
*/
static HeapTuple
ExtractReplicaIdentity(Relation relation, HeapTuple tp, bool key_required,
+ Bitmapset *logged_old_attrs,
bool *copy)
{
TupleDesc desc = RelationGetDescr(relation);
@@ -9164,13 +9198,16 @@ ExtractReplicaIdentity(Relation relation, HeapTuple tp, bool key_required,
}

/* if the key isn't required and we're only logging the key, we're done */
- if (!key_required)
+ if (!key_required && logged_old_attrs == NULL)
return NULL;

/* find out the replica identity columns */
idattrs = RelationGetIndexAttrBitmap(relation,
INDEX_ATTR_BITMAP_IDENTITY_KEY);

+ /* merge the columns that are marked LOG_OLD_VALUE */
+ idattrs = bms_union(idattrs, logged_old_attrs);
+
/*
* If there's no defined replica identity columns, treat as !key_required.
* (This case should not be reachable from heap_update, since that should
diff --git a/src/include/utils/attoptcache.h b/src/include/utils/attoptcache.h
index f684a772af5..6c965fede13 100644
--- a/src/include/utils/attoptcache.h
+++ b/src/include/utils/attoptcache.h
@@ -21,6 +21,8 @@ typedef struct AttributeOpts
int32 vl_len_; /* varlena header (do not touch directly!) */
float8 n_distinct;
float8 n_distinct_inherited;
+ bool log_old_value;
+ Oid delta_apply_function;
} AttributeOpts;

extern AttributeOpts *get_attribute_options(Oid attrelid, int attnum);
Loading
Loading