Skip to content
Draft
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
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