postgresql/src/test/subscription/t/002_types.pl

566 lines
18 KiB
Perl

# Copyright (c) 2021-2023, PostgreSQL Global Development Group
# This tests that more complex datatypes are replicated correctly
# by logical replication
use strict;
use warnings;
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
# Initialize publisher node
my $node_publisher = PostgreSQL::Test::Cluster->new('publisher');
$node_publisher->init(allows_streaming => 'logical');
$node_publisher->start;
# Create subscriber node
my $node_subscriber = PostgreSQL::Test::Cluster->new('subscriber');
$node_subscriber->init(allows_streaming => 'logical');
$node_subscriber->start;
# Create some preexisting content on publisher
my $ddl = qq(
CREATE EXTENSION hstore WITH SCHEMA public;
CREATE TABLE public.tst_one_array (
a INTEGER PRIMARY KEY,
b INTEGER[]
);
CREATE TABLE public.tst_arrays (
a INTEGER[] PRIMARY KEY,
b TEXT[],
c FLOAT[],
d INTERVAL[]
);
CREATE TYPE public.tst_enum_t AS ENUM ('a', 'b', 'c', 'd', 'e');
CREATE TABLE public.tst_one_enum (
a INTEGER PRIMARY KEY,
b public.tst_enum_t
);
CREATE TABLE public.tst_enums (
a public.tst_enum_t PRIMARY KEY,
b public.tst_enum_t[]
);
CREATE TYPE public.tst_comp_basic_t AS (a FLOAT, b TEXT, c INTEGER);
CREATE TYPE public.tst_comp_enum_t AS (a FLOAT, b public.tst_enum_t, c INTEGER);
CREATE TYPE public.tst_comp_enum_array_t AS (a FLOAT, b public.tst_enum_t[], c INTEGER);
CREATE TABLE public.tst_one_comp (
a INTEGER PRIMARY KEY,
b public.tst_comp_basic_t
);
CREATE TABLE public.tst_comps (
a public.tst_comp_basic_t PRIMARY KEY,
b public.tst_comp_basic_t[]
);
CREATE TABLE public.tst_comp_enum (
a INTEGER PRIMARY KEY,
b public.tst_comp_enum_t
);
CREATE TABLE public.tst_comp_enum_array (
a public.tst_comp_enum_t PRIMARY KEY,
b public.tst_comp_enum_t[]
);
CREATE TABLE public.tst_comp_one_enum_array (
a INTEGER PRIMARY KEY,
b public.tst_comp_enum_array_t
);
CREATE TABLE public.tst_comp_enum_what (
a public.tst_comp_enum_array_t PRIMARY KEY,
b public.tst_comp_enum_array_t[]
);
CREATE TYPE public.tst_comp_mix_t AS (
a public.tst_comp_basic_t,
b public.tst_comp_basic_t[],
c public.tst_enum_t,
d public.tst_enum_t[]
);
CREATE TABLE public.tst_comp_mix_array (
a public.tst_comp_mix_t PRIMARY KEY,
b public.tst_comp_mix_t[]
);
CREATE TABLE public.tst_range (
a INTEGER PRIMARY KEY,
b int4range
);
CREATE TABLE public.tst_range_array (
a INTEGER PRIMARY KEY,
b TSTZRANGE,
c int8range[]
);
CREATE TABLE public.tst_hstore (
a INTEGER PRIMARY KEY,
b public.hstore
);
SET check_function_bodies=off;
CREATE FUNCTION public.monot_incr(int) RETURNS bool LANGUAGE sql
AS ' select \$1 > max(a) from public.tst_dom_constr; ';
CREATE DOMAIN monot_int AS int CHECK (monot_incr(VALUE));
CREATE TABLE public.tst_dom_constr (a monot_int););
# Setup structure on both nodes
$node_publisher->safe_psql('postgres', $ddl);
$node_subscriber->safe_psql('postgres', $ddl);
# Setup logical replication
my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres';
$node_publisher->safe_psql('postgres',
"CREATE PUBLICATION tap_pub FOR ALL TABLES");
$node_subscriber->safe_psql('postgres',
"CREATE SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr' PUBLICATION tap_pub WITH (slot_name = tap_sub_slot)"
);
# Wait for initial sync to finish as well
$node_subscriber->wait_for_subscription_sync($node_publisher, 'tap_sub');
# Insert initial test data
$node_publisher->safe_psql(
'postgres', qq(
-- test_tbl_one_array_col
INSERT INTO tst_one_array (a, b) VALUES
(1, '{1, 2, 3}'),
(2, '{2, 3, 1}'),
(3, '{3, 2, 1}'),
(4, '{4, 3, 2}'),
(5, '{5, NULL, 3}');
-- test_tbl_arrays
INSERT INTO tst_arrays (a, b, c, d) VALUES
('{1, 2, 3}', '{"a", "b", "c"}', '{1.1, 2.2, 3.3}', '{"1 day", "2 days", "3 days"}'),
('{2, 3, 1}', '{"b", "c", "a"}', '{2.2, 3.3, 1.1}', '{"2 minutes", "3 minutes", "1 minute"}'),
('{3, 1, 2}', '{"c", "a", "b"}', '{3.3, 1.1, 2.2}', '{"3 years", "1 year", "2 years"}'),
('{4, 1, 2}', '{"d", "a", "b"}', '{4.4, 1.1, 2.2}', '{"4 years", "1 year", "2 years"}'),
('{5, NULL, NULL}', '{"e", NULL, "b"}', '{5.5, 1.1, NULL}', '{"5 years", NULL, NULL}');
-- test_tbl_single_enum
INSERT INTO tst_one_enum (a, b) VALUES
(1, 'a'),
(2, 'b'),
(3, 'c'),
(4, 'd'),
(5, NULL);
-- test_tbl_enums
INSERT INTO tst_enums (a, b) VALUES
('a', '{b, c}'),
('b', '{c, a}'),
('c', '{b, a}'),
('d', '{c, b}'),
('e', '{d, NULL}');
-- test_tbl_single_composites
INSERT INTO tst_one_comp (a, b) VALUES
(1, ROW(1.0, 'a', 1)),
(2, ROW(2.0, 'b', 2)),
(3, ROW(3.0, 'c', 3)),
(4, ROW(4.0, 'd', 4)),
(5, ROW(NULL, NULL, 5));
-- test_tbl_composites
INSERT INTO tst_comps (a, b) VALUES
(ROW(1.0, 'a', 1), ARRAY[ROW(1, 'a', 1)::tst_comp_basic_t]),
(ROW(2.0, 'b', 2), ARRAY[ROW(2, 'b', 2)::tst_comp_basic_t]),
(ROW(3.0, 'c', 3), ARRAY[ROW(3, 'c', 3)::tst_comp_basic_t]),
(ROW(4.0, 'd', 4), ARRAY[ROW(4, 'd', 3)::tst_comp_basic_t]),
(ROW(5.0, 'e', NULL), ARRAY[NULL, ROW(5, NULL, 5)::tst_comp_basic_t]);
-- test_tbl_composite_with_enums
INSERT INTO tst_comp_enum (a, b) VALUES
(1, ROW(1.0, 'a', 1)),
(2, ROW(2.0, 'b', 2)),
(3, ROW(3.0, 'c', 3)),
(4, ROW(4.0, 'd', 4)),
(5, ROW(NULL, 'e', NULL));
-- test_tbl_composite_with_enums_array
INSERT INTO tst_comp_enum_array (a, b) VALUES
(ROW(1.0, 'a', 1), ARRAY[ROW(1, 'a', 1)::tst_comp_enum_t]),
(ROW(2.0, 'b', 2), ARRAY[ROW(2, 'b', 2)::tst_comp_enum_t]),
(ROW(3.0, 'c', 3), ARRAY[ROW(3, 'c', 3)::tst_comp_enum_t]),
(ROW(4.0, 'd', 3), ARRAY[ROW(3, 'd', 3)::tst_comp_enum_t]),
(ROW(5.0, 'e', 3), ARRAY[ROW(3, 'e', 3)::tst_comp_enum_t, NULL]);
-- test_tbl_composite_with_single_enums_array_in_composite
INSERT INTO tst_comp_one_enum_array (a, b) VALUES
(1, ROW(1.0, '{a, b, c}', 1)),
(2, ROW(2.0, '{a, b, c}', 2)),
(3, ROW(3.0, '{a, b, c}', 3)),
(4, ROW(4.0, '{c, b, d}', 4)),
(5, ROW(5.0, '{NULL, e, NULL}', 5));
-- test_tbl_composite_with_enums_array_in_composite
INSERT INTO tst_comp_enum_what (a, b) VALUES
(ROW(1.0, '{a, b, c}', 1), ARRAY[ROW(1, '{a, b, c}', 1)::tst_comp_enum_array_t]),
(ROW(2.0, '{b, c, a}', 2), ARRAY[ROW(2, '{b, c, a}', 1)::tst_comp_enum_array_t]),
(ROW(3.0, '{c, a, b}', 1), ARRAY[ROW(3, '{c, a, b}', 1)::tst_comp_enum_array_t]),
(ROW(4.0, '{c, b, d}', 4), ARRAY[ROW(4, '{c, b, d}', 4)::tst_comp_enum_array_t]),
(ROW(5.0, '{c, NULL, b}', NULL), ARRAY[ROW(5, '{c, e, b}', 1)::tst_comp_enum_array_t]);
-- test_tbl_mixed_composites
INSERT INTO tst_comp_mix_array (a, b) VALUES
(ROW(
ROW(1,'a',1),
ARRAY[ROW(1,'a',1)::tst_comp_basic_t, ROW(2,'b',2)::tst_comp_basic_t],
'a',
'{a,b,NULL,c}'),
ARRAY[
ROW(
ROW(1,'a',1),
ARRAY[
ROW(1,'a',1)::tst_comp_basic_t,
ROW(2,'b',2)::tst_comp_basic_t,
NULL
],
'a',
'{a,b,c}'
)::tst_comp_mix_t
]
);
-- test_tbl_range
INSERT INTO tst_range (a, b) VALUES
(1, '[1, 10]'),
(2, '[2, 20]'),
(3, '[3, 30]'),
(4, '[4, 40]'),
(5, '[5, 50]');
-- test_tbl_range_array
INSERT INTO tst_range_array (a, b, c) VALUES
(1, tstzrange('Mon Aug 04 00:00:00 2014 CEST'::timestamptz, 'infinity'), '{"[1,2]", "[10,20]"}'),
(2, tstzrange('Sat Aug 02 00:00:00 2014 CEST'::timestamptz, 'Mon Aug 04 00:00:00 2014 CEST'::timestamptz), '{"[2,3]", "[20,30]"}'),
(3, tstzrange('Fri Aug 01 00:00:00 2014 CEST'::timestamptz, 'Mon Aug 04 00:00:00 2014 CEST'::timestamptz), '{"[3,4]"}'),
(4, tstzrange('Thu Jul 31 00:00:00 2014 CEST'::timestamptz, 'Mon Aug 04 00:00:00 2014 CEST'::timestamptz), '{"[4,5]", NULL, "[40,50]"}'),
(5, NULL, NULL);
-- tst_hstore
INSERT INTO tst_hstore (a, b) VALUES
(1, '"a"=>"1"'),
(2, '"zzz"=>"foo"'),
(3, '"123"=>"321"'),
(4, '"yellow horse"=>"moaned"');
-- tst_dom_constr
INSERT INTO tst_dom_constr VALUES (10);
));
$node_publisher->wait_for_catchup('tap_sub');
# Check the data on subscriber
my $result = $node_subscriber->safe_psql(
'postgres', qq(
SET timezone = '+2';
SELECT a, b FROM tst_one_array ORDER BY a;
SELECT a, b, c, d FROM tst_arrays ORDER BY a;
SELECT a, b FROM tst_one_enum ORDER BY a;
SELECT a, b FROM tst_enums ORDER BY a;
SELECT a, b FROM tst_one_comp ORDER BY a;
SELECT a, b FROM tst_comps ORDER BY a;
SELECT a, b FROM tst_comp_enum ORDER BY a;
SELECT a, b FROM tst_comp_enum_array ORDER BY a;
SELECT a, b FROM tst_comp_one_enum_array ORDER BY a;
SELECT a, b FROM tst_comp_enum_what ORDER BY a;
SELECT a, b FROM tst_comp_mix_array ORDER BY a;
SELECT a, b FROM tst_range ORDER BY a;
SELECT a, b, c FROM tst_range_array ORDER BY a;
SELECT a, b FROM tst_hstore ORDER BY a;
));
is( $result, '1|{1,2,3}
2|{2,3,1}
3|{3,2,1}
4|{4,3,2}
5|{5,NULL,3}
{1,2,3}|{a,b,c}|{1.1,2.2,3.3}|{"1 day","2 days","3 days"}
{2,3,1}|{b,c,a}|{2.2,3.3,1.1}|{00:02:00,00:03:00,00:01:00}
{3,1,2}|{c,a,b}|{3.3,1.1,2.2}|{"3 years","1 year","2 years"}
{4,1,2}|{d,a,b}|{4.4,1.1,2.2}|{"4 years","1 year","2 years"}
{5,NULL,NULL}|{e,NULL,b}|{5.5,1.1,NULL}|{"5 years",NULL,NULL}
1|a
2|b
3|c
4|d
5|
a|{b,c}
b|{c,a}
c|{b,a}
d|{c,b}
e|{d,NULL}
1|(1,a,1)
2|(2,b,2)
3|(3,c,3)
4|(4,d,4)
5|(,,5)
(1,a,1)|{"(1,a,1)"}
(2,b,2)|{"(2,b,2)"}
(3,c,3)|{"(3,c,3)"}
(4,d,4)|{"(4,d,3)"}
(5,e,)|{NULL,"(5,,5)"}
1|(1,a,1)
2|(2,b,2)
3|(3,c,3)
4|(4,d,4)
5|(,e,)
(1,a,1)|{"(1,a,1)"}
(2,b,2)|{"(2,b,2)"}
(3,c,3)|{"(3,c,3)"}
(4,d,3)|{"(3,d,3)"}
(5,e,3)|{"(3,e,3)",NULL}
1|(1,"{a,b,c}",1)
2|(2,"{a,b,c}",2)
3|(3,"{a,b,c}",3)
4|(4,"{c,b,d}",4)
5|(5,"{NULL,e,NULL}",5)
(1,"{a,b,c}",1)|{"(1,\"{a,b,c}\",1)"}
(2,"{b,c,a}",2)|{"(2,\"{b,c,a}\",1)"}
(3,"{c,a,b}",1)|{"(3,\"{c,a,b}\",1)"}
(4,"{c,b,d}",4)|{"(4,\"{c,b,d}\",4)"}
(5,"{c,NULL,b}",)|{"(5,\"{c,e,b}\",1)"}
("(1,a,1)","{""(1,a,1)"",""(2,b,2)""}",a,"{a,b,NULL,c}")|{"(\"(1,a,1)\",\"{\"\"(1,a,1)\"\",\"\"(2,b,2)\"\",NULL}\",a,\"{a,b,c}\")"}
1|[1,11)
2|[2,21)
3|[3,31)
4|[4,41)
5|[5,51)
1|["2014-08-04 00:00:00+02",infinity)|{"[1,3)","[10,21)"}
2|["2014-08-02 00:00:00+02","2014-08-04 00:00:00+02")|{"[2,4)","[20,31)"}
3|["2014-08-01 00:00:00+02","2014-08-04 00:00:00+02")|{"[3,5)"}
4|["2014-07-31 00:00:00+02","2014-08-04 00:00:00+02")|{"[4,6)",NULL,"[40,51)"}
5||
1|"a"=>"1"
2|"zzz"=>"foo"
3|"123"=>"321"
4|"yellow horse"=>"moaned"',
'check replicated inserts on subscriber');
# Run batch of updates
$node_publisher->safe_psql(
'postgres', qq(
UPDATE tst_one_array SET b = '{4, 5, 6}' WHERE a = 1;
UPDATE tst_one_array SET b = '{4, 5, 6, 1}' WHERE a > 3;
UPDATE tst_arrays SET b = '{"1a", "2b", "3c"}', c = '{1.0, 2.0, 3.0}', d = '{"1 day 1 second", "2 days 2 seconds", "3 days 3 second"}' WHERE a = '{1, 2, 3}';
UPDATE tst_arrays SET b = '{"c", "d", "e"}', c = '{3.0, 4.0, 5.0}', d = '{"3 day 1 second", "4 days 2 seconds", "5 days 3 second"}' WHERE a[1] > 3;
UPDATE tst_one_enum SET b = 'c' WHERE a = 1;
UPDATE tst_one_enum SET b = NULL WHERE a > 3;
UPDATE tst_enums SET b = '{e, NULL}' WHERE a = 'a';
UPDATE tst_enums SET b = '{e, d}' WHERE a > 'c';
UPDATE tst_one_comp SET b = ROW(1.0, 'A', 1) WHERE a = 1;
UPDATE tst_one_comp SET b = ROW(NULL, 'x', -1) WHERE a > 3;
UPDATE tst_comps SET b = ARRAY[ROW(9, 'x', -1)::tst_comp_basic_t] WHERE (a).a = 1.0;
UPDATE tst_comps SET b = ARRAY[NULL, ROW(9, 'x', NULL)::tst_comp_basic_t] WHERE (a).a > 3.9;
UPDATE tst_comp_enum SET b = ROW(1.0, NULL, NULL) WHERE a = 1;
UPDATE tst_comp_enum SET b = ROW(4.0, 'd', 44) WHERE a > 3;
UPDATE tst_comp_enum_array SET b = ARRAY[NULL, ROW(3, 'd', 3)::tst_comp_enum_t] WHERE a = ROW(1.0, 'a', 1)::tst_comp_enum_t;
UPDATE tst_comp_enum_array SET b = ARRAY[ROW(1, 'a', 1)::tst_comp_enum_t, ROW(2, 'b', 2)::tst_comp_enum_t] WHERE (a).a > 3;
UPDATE tst_comp_one_enum_array SET b = ROW(1.0, '{a, e, c}', NULL) WHERE a = 1;
UPDATE tst_comp_one_enum_array SET b = ROW(4.0, '{c, b, d}', 4) WHERE a > 3;
UPDATE tst_comp_enum_what SET b = ARRAY[NULL, ROW(1, '{a, b, c}', 1)::tst_comp_enum_array_t, ROW(NULL, '{a, e, c}', 2)::tst_comp_enum_array_t] WHERE (a).a = 1;
UPDATE tst_comp_enum_what SET b = ARRAY[ROW(5, '{a, b, c}', 5)::tst_comp_enum_array_t] WHERE (a).a > 3;
UPDATE tst_comp_mix_array SET b[2] = NULL WHERE ((a).a).a = 1;
UPDATE tst_range SET b = '[100, 1000]' WHERE a = 1;
UPDATE tst_range SET b = '(1, 90)' WHERE a > 3;
UPDATE tst_range_array SET c = '{"[100, 1000]"}' WHERE a = 1;
UPDATE tst_range_array SET b = tstzrange('Mon Aug 04 00:00:00 2014 CEST'::timestamptz, 'infinity'), c = '{NULL, "[11,9999999]"}' WHERE a > 3;
UPDATE tst_hstore SET b = '"updated"=>"value"' WHERE a < 3;
UPDATE tst_hstore SET b = '"also"=>"updated"' WHERE a = 3;
));
$node_publisher->wait_for_catchup('tap_sub');
# Check the data on subscriber
$result = $node_subscriber->safe_psql(
'postgres', qq(
SET timezone = '+2';
SELECT a, b FROM tst_one_array ORDER BY a;
SELECT a, b, c, d FROM tst_arrays ORDER BY a;
SELECT a, b FROM tst_one_enum ORDER BY a;
SELECT a, b FROM tst_enums ORDER BY a;
SELECT a, b FROM tst_one_comp ORDER BY a;
SELECT a, b FROM tst_comps ORDER BY a;
SELECT a, b FROM tst_comp_enum ORDER BY a;
SELECT a, b FROM tst_comp_enum_array ORDER BY a;
SELECT a, b FROM tst_comp_one_enum_array ORDER BY a;
SELECT a, b FROM tst_comp_enum_what ORDER BY a;
SELECT a, b FROM tst_comp_mix_array ORDER BY a;
SELECT a, b FROM tst_range ORDER BY a;
SELECT a, b, c FROM tst_range_array ORDER BY a;
SELECT a, b FROM tst_hstore ORDER BY a;
));
is( $result, '1|{4,5,6}
2|{2,3,1}
3|{3,2,1}
4|{4,5,6,1}
5|{4,5,6,1}
{1,2,3}|{1a,2b,3c}|{1,2,3}|{"1 day 00:00:01","2 days 00:00:02","3 days 00:00:03"}
{2,3,1}|{b,c,a}|{2.2,3.3,1.1}|{00:02:00,00:03:00,00:01:00}
{3,1,2}|{c,a,b}|{3.3,1.1,2.2}|{"3 years","1 year","2 years"}
{4,1,2}|{c,d,e}|{3,4,5}|{"3 days 00:00:01","4 days 00:00:02","5 days 00:00:03"}
{5,NULL,NULL}|{c,d,e}|{3,4,5}|{"3 days 00:00:01","4 days 00:00:02","5 days 00:00:03"}
1|c
2|b
3|c
4|
5|
a|{e,NULL}
b|{c,a}
c|{b,a}
d|{e,d}
e|{e,d}
1|(1,A,1)
2|(2,b,2)
3|(3,c,3)
4|(,x,-1)
5|(,x,-1)
(1,a,1)|{"(9,x,-1)"}
(2,b,2)|{"(2,b,2)"}
(3,c,3)|{"(3,c,3)"}
(4,d,4)|{NULL,"(9,x,)"}
(5,e,)|{NULL,"(9,x,)"}
1|(1,,)
2|(2,b,2)
3|(3,c,3)
4|(4,d,44)
5|(4,d,44)
(1,a,1)|{NULL,"(3,d,3)"}
(2,b,2)|{"(2,b,2)"}
(3,c,3)|{"(3,c,3)"}
(4,d,3)|{"(1,a,1)","(2,b,2)"}
(5,e,3)|{"(1,a,1)","(2,b,2)"}
1|(1,"{a,e,c}",)
2|(2,"{a,b,c}",2)
3|(3,"{a,b,c}",3)
4|(4,"{c,b,d}",4)
5|(4,"{c,b,d}",4)
(1,"{a,b,c}",1)|{NULL,"(1,\"{a,b,c}\",1)","(,\"{a,e,c}\",2)"}
(2,"{b,c,a}",2)|{"(2,\"{b,c,a}\",1)"}
(3,"{c,a,b}",1)|{"(3,\"{c,a,b}\",1)"}
(4,"{c,b,d}",4)|{"(5,\"{a,b,c}\",5)"}
(5,"{c,NULL,b}",)|{"(5,\"{a,b,c}\",5)"}
("(1,a,1)","{""(1,a,1)"",""(2,b,2)""}",a,"{a,b,NULL,c}")|{"(\"(1,a,1)\",\"{\"\"(1,a,1)\"\",\"\"(2,b,2)\"\",NULL}\",a,\"{a,b,c}\")",NULL}
1|[100,1001)
2|[2,21)
3|[3,31)
4|[2,90)
5|[2,90)
1|["2014-08-04 00:00:00+02",infinity)|{"[100,1001)"}
2|["2014-08-02 00:00:00+02","2014-08-04 00:00:00+02")|{"[2,4)","[20,31)"}
3|["2014-08-01 00:00:00+02","2014-08-04 00:00:00+02")|{"[3,5)"}
4|["2014-08-04 00:00:00+02",infinity)|{NULL,"[11,10000000)"}
5|["2014-08-04 00:00:00+02",infinity)|{NULL,"[11,10000000)"}
1|"updated"=>"value"
2|"updated"=>"value"
3|"also"=>"updated"
4|"yellow horse"=>"moaned"',
'check replicated updates on subscriber');
# Run batch of deletes
$node_publisher->safe_psql(
'postgres', qq(
DELETE FROM tst_one_array WHERE a = 1;
DELETE FROM tst_one_array WHERE b = '{2, 3, 1}';
DELETE FROM tst_arrays WHERE a = '{1, 2, 3}';
DELETE FROM tst_arrays WHERE a[1] = 2;
DELETE FROM tst_one_enum WHERE a = 1;
DELETE FROM tst_one_enum WHERE b = 'b';
DELETE FROM tst_enums WHERE a = 'a';
DELETE FROM tst_enums WHERE b[1] = 'b';
DELETE FROM tst_one_comp WHERE a = 1;
DELETE FROM tst_one_comp WHERE (b).a = 2.0;
DELETE FROM tst_comps WHERE (a).b = 'a';
DELETE FROM tst_comps WHERE ROW(3, 'c', 3)::tst_comp_basic_t = ANY(b);
DELETE FROM tst_comp_enum WHERE a = 1;
DELETE FROM tst_comp_enum WHERE (b).a = 2.0;
DELETE FROM tst_comp_enum_array WHERE a = ROW(1.0, 'a', 1)::tst_comp_enum_t;
DELETE FROM tst_comp_enum_array WHERE ROW(3, 'c', 3)::tst_comp_enum_t = ANY(b);
DELETE FROM tst_comp_one_enum_array WHERE a = 1;
DELETE FROM tst_comp_one_enum_array WHERE 'a' = ANY((b).b);
DELETE FROM tst_comp_enum_what WHERE (a).a = 1;
DELETE FROM tst_comp_enum_what WHERE (b[1]).b = '{c, a, b}';
DELETE FROM tst_comp_mix_array WHERE ((a).a).a = 1;
DELETE FROM tst_range WHERE a = 1;
DELETE FROM tst_range WHERE '[10,20]' && b;
DELETE FROM tst_range_array WHERE a = 1;
DELETE FROM tst_range_array WHERE tstzrange('Mon Aug 04 00:00:00 2014 CEST'::timestamptz, 'Mon Aug 05 00:00:00 2014 CEST'::timestamptz) && b;
DELETE FROM tst_hstore WHERE a = 1;
));
$node_publisher->wait_for_catchup('tap_sub');
# Check the data on subscriber
$result = $node_subscriber->safe_psql(
'postgres', qq(
SET timezone = '+2';
SELECT a, b FROM tst_one_array ORDER BY a;
SELECT a, b, c, d FROM tst_arrays ORDER BY a;
SELECT a, b FROM tst_one_enum ORDER BY a;
SELECT a, b FROM tst_enums ORDER BY a;
SELECT a, b FROM tst_one_comp ORDER BY a;
SELECT a, b FROM tst_comps ORDER BY a;
SELECT a, b FROM tst_comp_enum ORDER BY a;
SELECT a, b FROM tst_comp_enum_array ORDER BY a;
SELECT a, b FROM tst_comp_one_enum_array ORDER BY a;
SELECT a, b FROM tst_comp_enum_what ORDER BY a;
SELECT a, b FROM tst_comp_mix_array ORDER BY a;
SELECT a, b FROM tst_range ORDER BY a;
SELECT a, b, c FROM tst_range_array ORDER BY a;
SELECT a, b FROM tst_hstore ORDER BY a;
));
is( $result, '3|{3,2,1}
4|{4,5,6,1}
5|{4,5,6,1}
{3,1,2}|{c,a,b}|{3.3,1.1,2.2}|{"3 years","1 year","2 years"}
{4,1,2}|{c,d,e}|{3,4,5}|{"3 days 00:00:01","4 days 00:00:02","5 days 00:00:03"}
{5,NULL,NULL}|{c,d,e}|{3,4,5}|{"3 days 00:00:01","4 days 00:00:02","5 days 00:00:03"}
3|c
4|
5|
b|{c,a}
d|{e,d}
e|{e,d}
3|(3,c,3)
4|(,x,-1)
5|(,x,-1)
(2,b,2)|{"(2,b,2)"}
(4,d,4)|{NULL,"(9,x,)"}
(5,e,)|{NULL,"(9,x,)"}
3|(3,c,3)
4|(4,d,44)
5|(4,d,44)
(2,b,2)|{"(2,b,2)"}
(4,d,3)|{"(1,a,1)","(2,b,2)"}
(5,e,3)|{"(1,a,1)","(2,b,2)"}
4|(4,"{c,b,d}",4)
5|(4,"{c,b,d}",4)
(2,"{b,c,a}",2)|{"(2,\"{b,c,a}\",1)"}
(4,"{c,b,d}",4)|{"(5,\"{a,b,c}\",5)"}
(5,"{c,NULL,b}",)|{"(5,\"{a,b,c}\",5)"}
2|["2014-08-02 00:00:00+02","2014-08-04 00:00:00+02")|{"[2,4)","[20,31)"}
3|["2014-08-01 00:00:00+02","2014-08-04 00:00:00+02")|{"[3,5)"}
2|"updated"=>"value"
3|"also"=>"updated"
4|"yellow horse"=>"moaned"',
'check replicated deletes on subscriber');
# Test a domain with a constraint backed by a SQL-language function,
# which needs an active snapshot in order to operate.
$node_publisher->safe_psql('postgres',
"INSERT INTO tst_dom_constr VALUES (11)");
$node_publisher->wait_for_catchup('tap_sub');
$result =
$node_subscriber->safe_psql('postgres',
"SELECT sum(a) FROM tst_dom_constr");
is($result, '21', 'sql-function constraint on domain');
$node_subscriber->stop('fast');
$node_publisher->stop('fast');
done_testing();