Skip to content
Draft
Show file tree
Hide file tree
Changes from 9 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
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ ifdef SPOCK_RANDOM_DELAYS
PG_CPPFLAGS += -DSPOCK_RANDOM_DELAYS
endif
SHLIB_LINK += $(libpq) $(filter -lintl, $(LIBS))
ifdef NO_LOG_OLD_VALUE
PG_CPPFLAGS += -DNO_LOG_OLD_VALUE
endif

REGRESS := __placeholder__
EXTRA_CLEAN += $(control_path) spock_compat.bc \
Expand Down
1 change: 0 additions & 1 deletion include/spock.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
#define SPOCK_VERSION_NUM 60000

#define EXTENSION_NAME "spock"
#define SPOCK_SECLABEL_PROVIDER "spock"

#define REPLICATION_ORIGIN_ALL "all"

Expand Down
7 changes: 2 additions & 5 deletions include/spock_relcache.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,11 @@ typedef struct SpockRelation
Oid idxoid;
Relation rel;
int *attmap;
bool has_delta_columns;
Oid *delta_apply_functions;

/* Additional cache, only valid as long as relation mapping is. */
bool hasTriggers;

Oid *delta_apply_functions;
bool has_delta_columns;
} SpockRelation;

extern void spock_relation_cache_update(uint32 remoteid,
Expand All @@ -69,8 +68,6 @@ extern void spock_relation_cache_reset(void);

extern Oid spock_lookup_delta_function(char *fname, Oid typeoid);

extern Oid get_replication_identity(Relation rel);

struct SpockTupleData;

#endif /* SPOCK_RELCACHE_H */
198 changes: 198 additions & 0 deletions patches/15/pg15-015-attoptions.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index 620602fba2d..8eebc4cde65 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -168,6 +168,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}}
};
@@ -548,6 +557,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}}
};
@@ -2085,7 +2107,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 ef0e5eeca30..290cea25b12 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -67,6 +67,7 @@
#include "storage/smgr.h"
#include "storage/spin.h"
#include "storage/standby.h"
+#include "utils/attoptcache.h"
#include "utils/datum.h"
#include "utils/inval.h"
#include "utils/lsyscache.h"
@@ -88,6 +89,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,
@@ -122,6 +124,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 rel, HeapTuple tup, bool key_required,
+ Bitmapset *logged_old_attrs,
bool *copy);


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

/*
* If this is the first possibly-multixact-able operation in the current
@@ -3193,6 +3196,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;
@@ -3355,6 +3359,11 @@ 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
+ logged_old_attrs = NULL; /* No need to log old values for catalog tables */
+
/*
* 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
@@ -3625,6 +3634,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;
}
@@ -3961,6 +3971,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 */
@@ -4110,6 +4121,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;
@@ -4282,6 +4294,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.
*
@@ -9085,6 +9117,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);
@@ -9117,13 +9150,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 ee37af95001..98b48a8fd89 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 spcid, int attnum);
Loading
Loading