Implemented CRDTs#
Currently, six CRDT data types are implemented:
Grow-only counter and sum
Positive-negative counter and sum
Delta counter and sum
The counters and sums behave mostly the same, except that the counter
types are integer based (bigint ), while the sum types are
decimal-based (numeric ).
You can list the currently implemented CRDT data types with the following query:
SELECT n.nspname, t.typname
FROM bdr.crdt_handlers c
JOIN (pg_type t JOIN pg_namespace n ON t.typnamespace = n.oid)
ON t.oid = c.crdt_type_id;
Grow-only counter (crdt_gcounter )#
Supports only increments with nonnegative values (
value + intandcounter + bigintoperators).You can obtain the current value of the counter either using
#operator or by casting it tobigint.Isn’t compatible with simple assignments like
counter = value(which is common pattern when the new value is computed somewhere in the application).Allows simple reset of the counter using the
!operator (counter = !counter).You can inspect the internal state using
crdt_gcounter_to_text.
CREATE TABLE crdt_test (
id INT PRIMARY KEY,
cnt bdr.crdt_gcounter NOT NULL DEFAULT 0
);
INSERT INTO crdt_test VALUES (1, 0); -- initialized to 0
INSERT INTO crdt_test VALUES (2, 129824); -- initialized to 129824
INSERT INTO crdt_test VALUES (3, -4531); -- error: negative value
- - enable CLCD on the table
ALTER TABLE crdt_test REPLICA IDENTITY FULL;
SELECT bdr.alter_table_conflict_detection(crdt_test, column_modify_timestamp, cts);
- - increment counters
UPDATE crdt_test SET cnt = cnt + 1 WHERE id = 1;
UPDATE crdt_test SET cnt = cnt + 120 WHERE id = 2;
- - error: minus operator not defined
UPDATE crdt_test SET cnt = cnt - 1 WHERE id = 1;
- - error: increment has to be non-negative
UPDATE crdt_test SET cnt = cnt + (-1) WHERE id = 1;
- - reset counter
UPDATE crdt_test SET cnt = !cnt WHERE id = 1;
- - get current counter value
SELECT id, cnt::bigint, cnt FROM crdt_test;
- - show internal structure of counters
SELECT id, bdr.crdt_gcounter_to_text(cnt) FROM crdt_test;
Grow-only sum (crdt_gsum )#
Supports only increments with nonnegative values (
sum + numeric).You can obtain the current value of the sum either by using the
#operator or by casting it tonumeric.Isn’t compatible with simple assignments like
sum = value, which is the common pattern when the new value is computed somewhere in the application.Allows simple reset of the sum using the
!operator (sum = !sum).Can inspect internal state using
crdt_gsum_to_text.
CREATE TABLE crdt_test (
id INT PRIMARY KEY,
gsum bdr.crdt_gsum NOT NULL DEFAULT 0.0
);
INSERT INTO crdt_test VALUES (1, 0.0); -- initialized to 0
INSERT INTO crdt_test VALUES (2, 1298.24); -- initialized to 1298.24
INSERT INTO crdt_test VALUES (3, -45.31); -- error: negative value
- - enable CLCD on the table
ALTER TABLE crdt_test REPLICA IDENTITY FULL;
SELECT bdr.alter_table_conflict_detection(crdt_test, column_modify_timestamp, cts);
- - increment sum
UPDATE crdt_test SET gsum = gsum + 11.5 WHERE id = 1;
UPDATE crdt_test SET gsum = gsum + 120.33 WHERE id = 2;
- - error: minus operator not defined
UPDATE crdt_test SET gsum = gsum - 15.2 WHERE id = 1;
- - error: increment has to be non-negative
UPDATE crdt_test SET gsum = gsum + (-1.56) WHERE id = 1;
- - reset sum
UPDATE crdt_test SET gsum = !gsum WHERE id = 1;
- - get current sum value
SELECT id, gsum::numeric, gsum FROM crdt_test;
- - show internal structure of sums
SELECT id, bdr.crdt_gsum_to_text(gsum) FROM crdt_test;
Positive-negative counter (crdt_pncounter )#
Supports increments with both positive and negative values (through
counter + intandcounter + bigintoperators).You can obtain the current value of the counter either by using the
#operator or by casting tobigint.Isn’t compatible with simple assignments like
counter = value, which is the common pattern when the new value is computed somewhere in the application.Allows simple reset of the counter using the
!operator (counter = !counter).You can inspect the internal state using
crdt_pncounter_to_text.
CREATE TABLE crdt_test (
id INT PRIMARY KEY,
cnt bdr.crdt_pncounter NOT NULL DEFAULT 0
);
INSERT INTO crdt_test VALUES (1, 0); -- initialized to 0
INSERT INTO crdt_test VALUES (2, 129824); -- initialized to 129824
INSERT INTO crdt_test VALUES (3, -4531); -- initialized to -4531
- - enable CLCD on the table
ALTER TABLE crdt_test REPLICA IDENTITY FULL;
SELECT bdr.alter_table_conflict_detection(crdt_test, column_modify_timestamp, cts);
- - increment counters
UPDATE crdt_test SET cnt = cnt + 1 WHERE id = 1;
UPDATE crdt_test SET cnt = cnt + 120 WHERE id = 2;
UPDATE crdt_test SET cnt = cnt + (-244) WHERE id = 3;
- - decrement counters
UPDATE crdt_test SET cnt = cnt - 73 WHERE id = 1;
UPDATE crdt_test SET cnt = cnt - 19283 WHERE id = 2;
UPDATE crdt_test SET cnt = cnt - (-12) WHERE id = 3;
- - get current counter value
SELECT id, cnt::bigint, cnt FROM crdt_test;
- - show internal structure of counters
SELECT id, bdr.crdt_pncounter_to_text(cnt) FROM crdt_test;
- - reset counter
UPDATE crdt_test SET cnt = !cnt WHERE id = 1;
- - get current counter value after the reset
SELECT id, cnt::bigint, cnt FROM crdt_test;
Positive-negative sum (crdt_pnsum )#
Supports increments with both positive and negative values through
sum + numeric.You can obtain the current value of the sum either by using then
#operator or by casting tonumeric.Isn’t compatible with simple assignments like
sum = value, which is the common pattern when the new value is computed somewhere in the application.Allows simple reset of the sum using the
!operator (sum = !sum).You can inspect the internal state using
crdt_pnsum_to_text.
CREATE TABLE crdt_test (
id INT PRIMARY KEY,
pnsum bdr.crdt_pnsum NOT NULL DEFAULT 0
);
INSERT INTO crdt_test VALUES (1, 0); -- initialized to 0
INSERT INTO crdt_test VALUES (2, 1298.24); -- initialized to 1298.24
INSERT INTO crdt_test VALUES (3, -45.31); -- initialized to -45.31
- - enable CLCD on the table
ALTER TABLE crdt_test REPLICA IDENTITY FULL;
SELECT bdr.alter_table_conflict_detection(crdt_test, column_modify_timestamp, cts);
- - increment sums
UPDATE crdt_test SET pnsum = pnsum + 1.44 WHERE id = 1;
UPDATE crdt_test SET pnsum = pnsum + 12.20 WHERE id = 2;
UPDATE crdt_test SET pnsum = pnsum + (-24.34) WHERE id = 3;
- - decrement sums
UPDATE crdt_test SET pnsum = pnsum - 7.3 WHERE id = 1;
UPDATE crdt_test SET pnsum = pnsum - 192.83 WHERE id = 2;
UPDATE crdt_test SET pnsum = pnsum - (-12.22) WHERE id = 3;
- - get current sum value
SELECT id, pnsum::numeric, pnsum FROM crdt_test;
- - show internal structure of sum
SELECT id, bdr.crdt_pnsum_to_text(pnsum) FROM crdt_test;
- - reset sum
UPDATE crdt_test SET pnsum = !pnsum WHERE id = 1;
- - get current sum value after the reset
SELECT id, pnsum::numeric, pnsum FROM crdt_test;
Delta counter (crdt_delta_counter )#
Is defined a
bigintdomain, so works exactly like abigintcolumn.Supports increments with both positive and negative values.
Is compatible with simple assignments like
counter = value, which is common when the new value is computed somewhere in the application.There’s no simple way to reset the value reliably.
CREATE TABLE crdt_test (
id INT PRIMARY KEY,
cnt bdr.crdt_delta_counter NOT NULL DEFAULT 0
);
INSERT INTO crdt_test VALUES (1, 0); -- initialized to 0
INSERT INTO crdt_test VALUES (2, 129824); -- initialized to 129824
INSERT INTO crdt_test VALUES (3, -4531); -- initialized to -4531
- - enable CLCD on the table
ALTER TABLE crdt_test REPLICA IDENTITY FULL;
SELECT bdr.alter_table_conflict_detection(crdt_test, column_modify_timestamp, cts);
- - increment counters
UPDATE crdt_test SET cnt = cnt + 1 WHERE id = 1;
UPDATE crdt_test SET cnt = cnt + 120 WHERE id = 2;
UPDATE crdt_test SET cnt = cnt + (-244) WHERE id = 3;
- - decrement counters
UPDATE crdt_test SET cnt = cnt - 73 WHERE id = 1;
UPDATE crdt_test SET cnt = cnt - 19283 WHERE id = 2;
UPDATE crdt_test SET cnt = cnt - (-12) WHERE id = 3;
- - get current counter value
SELECT id, cnt FROM crdt_test;
Delta sum (crdt_delta_sum )#
Is defined as a
numericdomain so works exactly like anumericcolumn.Supports increments with both positive and negative values.
Is compatible with simple assignments like
sum = value, which is common when the new value is computed somewhere in the application.There’s no simple way to reset the value reliably.
CREATE TABLE crdt_test (
id INT PRIMARY KEY,
dsum bdr.crdt_delta_sum NOT NULL DEFAULT 0
);
INSERT INTO crdt_test VALUES (1, 0); -- initialized to 0
INSERT INTO crdt_test VALUES (2, 129.824); -- initialized to 129824
INSERT INTO crdt_test VALUES (3, -4.531); -- initialized to -4531
- - enable CLCD on the table
ALTER TABLE crdt_test REPLICA IDENTITY FULL;
SELECT bdr.alter_table_conflict_detection(crdt_test, column_modify_timestamp, cts);
- - increment counters
UPDATE crdt_test SET dsum = dsum + 1.32 WHERE id = 1;
UPDATE crdt_test SET dsum = dsum + 12.01 WHERE id = 2;
UPDATE crdt_test SET dsum = dsum + (-2.4) WHERE id = 3;
- - decrement counters
UPDATE crdt_test SET dsum = dsum - 7.33 WHERE id = 1;
UPDATE crdt_test SET dsum = dsum - 19.83 WHERE id = 2;
UPDATE crdt_test SET dsum = dsum - (-1.2) WHERE id = 3;
- - get current counter value
SELECT id, cnt FROM crdt_test;