#!/usr/bin/env bash

mkdir publisher
./initdb -D publisher

cat << EOF >> publisher/postgresql.conf
wal_level = logical
wal_sender_timeout = 0
EOF

cat << EOF >> publisher/pg_hba.conf
host   all all	0.0.0.0/0	trust
EOF

./pg_ctl start -D publisher -l publisher.log

./psql -d postgres -c "
CREATE TABLE tab_full (a int, b text);
ALTER TABLE tab_full REPLICA IDENTITY FULL;

-- Publisher-side replica identity is FULL for all three tables below.
-- The subscriber-side replica identity is intentionally changed later to
-- NOTHING for tab_nothing and DEFAULT-without-PK for tab_nopk.
CREATE TABLE tab_nothing (a int, b text);
ALTER TABLE tab_nothing REPLICA IDENTITY FULL;

CREATE TABLE tab_nopk (a int, b text);
ALTER TABLE tab_nopk REPLICA IDENTITY FULL;

CREATE TABLE tab_pk (a int PRIMARY KEY, b text);
CREATE PUBLICATION pub
    FOR TABLE tab_full, tab_nothing, tab_nopk, tab_pk;
INSERT INTO tab_full VALUES (1, 'from publisher');
INSERT INTO tab_nothing VALUES (1, 'from publisher');
INSERT INTO tab_nopk VALUES (1, 'from publisher');
INSERT INTO tab_pk VALUES (1, 'from publisher');
"

#!/usr/bin/env bash

cluster_name=subscriber
./initdb -D $cluster_name
cat << EOF >> $cluster_name/postgresql.conf
port = 5433
track_commit_timestamp = on
EOF

cat << EOF >> $cluster_name/pg_hba.conf
host	all	all	0.0.0.0/0	trust
EOF

./pg_ctl start -D $cluster_name -l $cluster_name.log

./psql -d postgres -p 5433 -c "
CREATE TABLE tab_full (a int, b text);
ALTER TABLE tab_full REPLICA IDENTITY FULL;

-- Subscriber-side replica identity is NOTHING.
-- GetRelationIdentityOrPK() returns InvalidOid for this case, but this
-- does NOT mean REPLICA IDENTITY FULL.
CREATE TABLE tab_nothing (a int, b text);
ALTER TABLE tab_nothing REPLICA IDENTITY NOTHING;

-- Subscriber-side replica identity is DEFAULT with no primary key.
-- GetRelationIdentityOrPK() also returns InvalidOid for this case.
-- This is another case that must not be reported as REPLICA IDENTITY FULL.
CREATE TABLE tab_nopk (a int, b text);

-- Subscriber-side DEFAULT with a primary key has a valid replica identity
-- index, so GetRelationIdentityOrPK() returns the primary-key index OID.
CREATE TABLE tab_pk (a int PRIMARY KEY, b text);"

./psql -d postgres -p 5433 -c "CREATE SUBSCRIPTION sub1 CONNECTION 'host=localhost port=5432 dbname=postgres' PUBLICATION pub with (conflict_log_destination = 'table')"

sleep 1

./psql -d postgres -p 5433 -c "	UPDATE tab_full SET b = b;
	UPDATE tab_nothing SET b = b;
	UPDATE tab_nopk SET b = b;
	UPDATE tab_pk SET b = b;
"

./psql -d postgres -c "UPDATE tab_full SET b = 'from subscriber conflict';
	UPDATE tab_nothing SET b = 'from subscriber conflict';
	UPDATE tab_nopk SET b = 'from subscriber conflict';
	UPDATE tab_pk SET b = 'from subscriber conflict';"

sleep 3

## Subscriber's actual replica identity configuration:
##   tab_full    : 'f' = REPLICA IDENTITY FULL
##   tab_nothing : 'n' = REPLICA IDENTITY NOTHING
##   tab_nopk    : 'd' = REPLICA IDENTITY DEFAULT, with no primary key
##   tab_pk      : 'd' = REPLICA IDENTITY DEFAULT, with a primary key
./psql -d postgres -p 5433 -c "SELECT relname, relreplident FROM pg_class WHERE relname IN
('tab_full', 'tab_nothing', 'tab_nopk', 'tab_pk');"

conflict_log_relid=$(./psql -d postgres -p 5433 -Atc \
  "SELECT oid FROM pg_subscription WHERE subname = 'sub1';")

## Conflict log result:
##   tab_full    : t  -> correct; the relation uses REPLICA IDENTITY FULL.
##   tab_nothing : t  -> incorrect; the relation uses REPLICA IDENTITY NOTHING.
##   tab_nopk    : t  -> incorrect; the relation uses REPLICA IDENTITY DEFAULT
##                       and has no primary key.
##   tab_pk      : f  -> correct; the primary-key index is used as the
##                       replica identity.
./psql -d postgres -p 5433 -c \
  "SELECT relname, replica_identity_full
   FROM pg_conflict.pg_conflict_log_${conflict_log_relid};"

