#!/bin/bash

port_N1=7651
port_N2=7652
port_N3=7653
port_N4=7654
port_N5=7655

common_tbl="create table tbl (a int primary key);"
copy_false="subscribe_local_only=true,copy_data=false"
copy_force="subscribe_local_only=true,copy_data=force"

function show_table_on_all_nodes()
{
	echo $1
	psql -p $port_N1 -c "select a as N1 from tbl order by a"
	psql -p $port_N2 -c "select a as N2 from tbl order by a"
	psql -p $port_N3 -c "select a as N3 from tbl order by a"
	psql -p $port_N4 -c "select a as N4 from tbl order by a"
	psql -p $port_N5 -c "select a as N5 from tbl order by a"
}

echo 'Clean up'

pg_ctl stop -D data_N1
pg_ctl stop -D data_N2
pg_ctl stop -D data_N3
pg_ctl stop -D data_N4
pg_ctl stop -D data_N5

rm -r data_N1 data_N2 data_N3 data_N4 data_N5 *log

echo 'Set up'

initdb -D data_N1
initdb -D data_N2
initdb -D data_N3
initdb -D data_N4
initdb -D data_N5

cat << EOF >> data_N1/postgresql.conf
wal_level = logical
port = $port_N1
max_logical_replication_workers=100
max_replication_slots=40
autovacuum = off
EOF

cat << EOF >> data_N2/postgresql.conf
wal_level = logical
port = $port_N2
max_logical_replication_workers=100
max_replication_slots=40
autovacuum = off
EOF

cat << EOF >> data_N3/postgresql.conf
wal_level = logical
port = $port_N3
max_logical_replication_workers=100
max_replication_slots=40
autovacuum = off
EOF

cat << EOF >> data_N4/postgresql.conf
wal_level = logical
port = $port_N4
max_logical_replication_workers=100
max_replication_slots=40
autovacuum = off
EOF

cat << EOF >> data_N5/postgresql.conf
wal_level = logical
port = $port_N5
max_logical_replication_workers=100
max_replication_slots=40
autovacuum = off
EOF

pg_ctl -D data_N1 start -w -l N1.log
pg_ctl -D data_N2 start -w -l N2.log
pg_ctl -D data_N3 start -w -l N3.log 
pg_ctl -D data_N4 start -w -l N4.log
pg_ctl -D data_N5 start -w -l N5.log

psql -p $port_N1 -c "$common_tbl"
psql -p $port_N2 -c "$common_tbl"
psql -p $port_N3 -c "$common_tbl"
psql -p $port_N4 -c "$common_tbl"
psql -p $port_N5 -c "$common_tbl"

# =====================================================================================================================

echo '****************************************'
echo 'Initial table data for all nodes'
echo '****************************************'

# Insert some initial data for the table at each node
psql -p $port_N1 -c "insert into tbl values (10);"
psql -p $port_N2 -c "insert into tbl values (20);"
psql -p $port_N3 -c "insert into tbl values (30);"
psql -p $port_N4 -c "insert into tbl values (40);"
psql -p $port_N5 -c "insert into tbl values (50);"

sleep 10s
show_table_on_all_nodes "Initial data on all nodes"

# =====================================================================================================================

echo '****************************************'
echo 'Share table data for nodes N1,N2'
echo '****************************************'

# setup the pub/sub to join N1 and N2
psql -p $port_N1 -c "create publication pub1 for table tbl;"
psql -p $port_N2 -c "create publication pub2 for table tbl;"

# N1 copies N2 initial data
psql -p $port_N1 -c "create subscription sub12 connection 'port=$port_N2' publication pub2 with ($copy_force);"

sleep 5s

# Truncate the N2 data but do not replicate the truncate.
# Subscribe to N1 (this will give N2 its initial data back using copy_data=force)
psql -p $port_N2 << EOF
alter publication pub2 set (publish='insert,update,delete');
truncate tbl;
create subscription sub21 connection 'port=$port_N1' publication pub1 with ($copy_force);
alter publication pub2 set (publish='insert,update,delete,truncate');
EOF

sleep 10s
show_table_on_all_nodes "Initial data of N1,N2 should be shared"

# Insert some more data at every node to see that it is replicated everywhere
psql -p $port_N1 -c "insert into tbl values (12);"
psql -p $port_N2 -c "insert into tbl values (22);"

sleep 10s
show_table_on_all_nodes "Data inserted at N1,N2 should be shared"

# =====================================================================================================================

echo '****************************************'
echo 'Share table data for nodes N1,N2,N3'
echo '****************************************'

# setup the pub/sub to join N3 to existing group of N1,N2
psql -p $port_N3 -c "create publication pub3 for table tbl;"

# N1 copies N3 initial data
# N2 copies N3 initial data
psql -p $port_N1 -c "create subscription sub13 connection 'port=$port_N3' publication pub3 with ($copy_force);"
psql -p $port_N2 -c "create subscription sub23 connection 'port=$port_N3' publication pub3 with ($copy_force);"

sleep 5s

# Truncate the N3 data but do not replicate the truncate.
# Subscribe to N1 (this will give N3 its initial data back using copy_data=force)
# Subscribe to N2 (N3 already got the N1/N2 initial data from N1 so copy_data=false here)
psql -p $port_N3 << EOF
alter publication pub3 set (publish='insert,update,delete');
truncate tbl;
create subscription sub31 connection 'port=$port_N1' publication pub1 with ($copy_force);
create subscription sub32 connection 'port=$port_N2' publication pub2 with ($copy_false);
alter publication pub3 set (publish='insert,update,delete,truncate');
EOF

sleep 10s
show_table_on_all_nodes "Initial data of N1,N2,N3 should be shared"

# Insert some more data at every node to see that it is replicated everywhere
psql -p $port_N1 -c "insert into tbl values (13)"
psql -p $port_N2 -c "insert into tbl values (23);"
psql -p $port_N3 -c "insert into tbl values (33);"

sleep 10s
show_table_on_all_nodes "Data inserted at N1,N2,N3 should be shared"

# =====================================================================================================================

echo '****************************************'
echo 'Share table data for nodes N1,N2,N3,N4'
echo '****************************************'

# setup the pub/sub to join N4 to existing group of N1,N2,N3
psql -p $port_N4 -c "create publication pub4 for table tbl;"

# N1 copies N4 initial data
# N2 copies N4 initial data
# N3 copies N4 initial data
psql -p $port_N1 -c "create subscription sub14 connection 'port=$port_N4' publication pub4 with ($copy_force);"
psql -p $port_N2 -c "create subscription sub24 connection 'port=$port_N4' publication pub4 with ($copy_force);"
psql -p $port_N3 -c "create subscription sub34 connection 'port=$port_N4' publication pub4 with ($copy_force);"

sleep 5s

# Truncate the N4 data but do not replicate the truncate.
# Subscribe to N1 (this will give N4 its initial data back using copy_data=force)
# Subscribe to N2 (N4 already got the N1/N2/N3 initial data from N1 so copy_data=false here)
# Subscribe to N3 (N4 already got the N1/N2/N3 initial data from N1 so copy_data=false here)
psql -p $port_N4 << EOF
alter publication pub4 set (publish='insert,update,delete');
truncate tbl;
create subscription sub41 connection 'port=$port_N1' publication pub1 with ($copy_force);
create subscription sub42 connection 'port=$port_N2' publication pub2 with ($copy_false);
create subscription sub43 connection 'port=$port_N3' publication pub3 with ($copy_false);
alter publication pub4 set (publish='insert,update,delete,truncate');
EOF

sleep 10s
show_table_on_all_nodes "Initial data of N1,N2,N3,N4 should be shared"

# Insert some more data at every node to see that it is replicated everywhere
psql -p $port_N1 -c "insert into tbl values (14)"
psql -p $port_N2 -c "insert into tbl values (24);"
psql -p $port_N3 -c "insert into tbl values (34);"
psql -p $port_N4 -c "insert into tbl values (44);"

sleep 10s
show_table_on_all_nodes "Data inserted at N1,N2,N3,N4 should be shared"

# =====================================================================================================================

echo '****************************************'
echo 'Share table data for nodes N1,N2,N3,N4,N5'
echo '****************************************'

# setup the pub/sub to join N5 to existing group of N1,N2,N3,N4
psql -p $port_N5 -c "create publication pub5 for table tbl;"

# N1 copies N5 initial data
# N2 copies N5 initial data
# N3 copies N5 initial data
# N4 copies N5 initial data
psql -p $port_N1 -c "create subscription sub15 connection 'port=$port_N5' publication pub5 with ($copy_force);"
psql -p $port_N2 -c "create subscription sub25 connection 'port=$port_N5' publication pub5 with ($copy_force);"
psql -p $port_N3 -c "create subscription sub35 connection 'port=$port_N5' publication pub5 with ($copy_force);"
psql -p $port_N4 -c "create subscription sub45 connection 'port=$port_N5' publication pub5 with ($copy_force);"

sleep 10s

# Truncate the N5 data but do not replicate the truncate.
# Subscribe to N1 (this will give N5 its initial data back using copy_data=force)
# Subscribe to N2 (N5 already got the N1/N2/N3/N4 initial data from N1 so copy_data=false here)
# Subscribe to N3 (N5 already got the N1/N2/N3/N4 initial data from N1 so copy_data=false here)
# Subscribe to N4 (N5 already got the N1/N2/N3/N4 initial data from N1 so copy_data=false here)
psql -p $port_N5 << EOF
alter publication pub5 set (publish='insert,update,delete');
truncate tbl;
create subscription sub51 connection 'port=$port_N1' publication pub1 with ($copy_force);
create subscription sub52 connection 'port=$port_N2' publication pub2 with ($copy_false);
create subscription sub53 connection 'port=$port_N3' publication pub3 with ($copy_false);
create subscription sub54 connection 'port=$port_N4' publication pub4 with ($copy_false);
alter publication pub5 set (publish='insert,update,delete,truncate');
EOF

sleep 10s
show_table_on_all_nodes "Initial data of N1,N2,N3,N4,N5 should be shared"

# Insert some more data at every node to see that it is replicated everywhere
psql -p $port_N1 -c "insert into tbl values (15)"
psql -p $port_N2 -c "insert into tbl values (25);"
psql -p $port_N3 -c "insert into tbl values (35);"
psql -p $port_N4 -c "insert into tbl values (45);"
psql -p $port_N5 -c "insert into tbl values (55);"

sleep 10s
show_table_on_all_nodes "Data inserted at N1,N2,N3,N4,N5 should be shared"

