Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1nSOAs-0005Qz-U4 for pgsql-hackers@arkaria.postgresql.org; Thu, 10 Mar 2022 19:10:11 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1nSOAr-0007Y9-A2 for pgsql-hackers@arkaria.postgresql.org; Thu, 10 Mar 2022 19:10:09 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1nSOAq-0007Y0-HS for pgsql-hackers@lists.postgresql.org; Thu, 10 Mar 2022 19:10:09 +0000 Received: from mail-ej1-x62f.google.com ([2a00:1450:4864:20::62f]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1nSOAn-0003K2-Dz for pgsql-hackers@postgresql.org; Thu, 10 Mar 2022 19:10:07 +0000 Received: by mail-ej1-x62f.google.com with SMTP id a8so14238484ejc.8 for ; Thu, 10 Mar 2022 11:10:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=enterprisedb.com; s=google; h=message-id:date:mime-version:user-agent:subject:content-language :from:to:cc:references:in-reply-to:content-transfer-encoding; bh=PeMeXUBzU9dx+7lVHSHGjOV/apfpuNclh2F+cGnGto0=; b=TyotAWthNTvGvAVyOtZaygTtpN+SyU7jaie2ccfNPH17d1z6eL6PTOG/QhSa8SI1sm qA663GCuHXRoF1ACwKikTCJ09egnNQRZeUbF7h92VpjUJ2vqRLyc55t6iIkXgx+8FtAd oRk6iSmnMmcfCJiXbrRQvAgKrXi2Ja065JXm1lze5FKdMaLT3BdHREiq2Rn4G+VjZpkX 3QqLCDg1bwLTH7DdLlYP9NdmTr2ITIbMRBOezr4vPIhw8fQMQqyjbAZLl9KLYph1vhc1 tgcsPEPMN7iChBFi7cFh21i7uH/wlVR/vvBkadX7jqi/F5WDG4BmqtikgwWcnS2l6quM 8Mog== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:date:mime-version:user-agent:subject :content-language:from:to:cc:references:in-reply-to :content-transfer-encoding; bh=PeMeXUBzU9dx+7lVHSHGjOV/apfpuNclh2F+cGnGto0=; b=NpSqVGhirKm3tJGG5+F2qCfYiwBjdmF60EvlDC/xtmyUp1MJeKj/aenlSroKLGTsjF YZGpiCYc+e/8GOqzQMxDETHJ7UXPxH3PH4Xq5xfsGytNG5G07mfZkC4rOoUV8U092/HJ PJ/ff9n8wCpn/zSWRNYL9Y6jA9k9gj/08prHNdYDlgOHJxBj3+ziJAXpqeni8/nKl4II /YxcrG+fnXK8rO2Ua7JNe39sIFsGoL2BH17GaWBMmjHOB9lhzh6GW3NbNcLIX6PSArZK mvfA9QiZg6d8LOVe3Po1e4uDQlpTOSSFQbVBpBpPtsdg1zrbCMWc5Vki3F/d/Weop6F2 4F1A== X-Gm-Message-State: AOAM533X1u1ZXs6HeAo6iRS0J5HmlUXQFd4Dr74yasYNPG5AoIWRv9Th R1SRRspFF219Xrytk+7kyWy9YiXMczaB+S3t1kv9MumXJzWXxXMkfQ3/syjfD66Fn4JIGz+WkyN wOwFhQdx6pJAAubOX4ZrqvgUyn0CiOOIRe8fTKD+u4iCbzvMx+n/y5untRY7k8vuWcyxlTQFAYk T1KHbTVrC5r91prDRgoOu+Lk5dGvdcYJ5XKmth X-Google-Smtp-Source: ABdhPJwr1DKL6z/qIe+BaNUmR61oW9zXiuLhOHp66q/ukCNSncaednpsGWGBpeWacjfw6e7EOv47Jw== X-Received: by 2002:a17:907:3f24:b0:6da:68fa:b2cc with SMTP id hq36-20020a1709073f2400b006da68fab2ccmr5551983ejc.734.1646939403766; Thu, 10 Mar 2022 11:10:03 -0800 (PST) Received: from [10.137.0.18] (static-84-42-175-93.net.upcbroadband.cz. [84.42.175.93]) by smtp.gmail.com with ESMTPSA id q15-20020a056402518f00b00416a3194924sm1824982edd.75.2022.03.10.11.10.03 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 10 Mar 2022 11:10:03 -0800 (PST) Message-ID: <78b8d385-57cb-9a3f-cfe5-9f300f15eced@enterprisedb.com> Date: Thu, 10 Mar 2022 20:10:01 +0100 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.5.0 Subject: Re: Column Filtering in Logical Replication Content-Language: en-US From: Tomas Vondra To: "houzj.fnst@fujitsu.com" , Amit Kapila Cc: Peter Eisentraut , Alvaro Herrera , Justin Pryzby , Rahila Syed , Peter Smith , pgsql-hackers , "shiy.fnst@fujitsu.com" References: <202201120041.p24wvsfcsope@alvherre.pgsql> In-Reply-To: Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-CLOUD-SEC-AV-Info: enterprisedb,google_mail,monitor X-CLOUD-SEC-AV-Sent: true X-Gm-Spam: 0 X-Gm-Phishy: 0 List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On 3/10/22 19:17, Tomas Vondra wrote: > On 3/9/22 11:12, houzj.fnst@fujitsu.com wrote: >> Hi, >> >> Here are some tests and results about the table sync query of >> column filter patch and row filter. >> >> 1) multiple publications which publish schema of parent table and partition. >> ----pub >> create schema s1; >> create table s1.t (a int, b int, c int) partition by range (a); >> create table t_1 partition of s1.t for values from (1) to (10); >> create publication pub1 for all tables in schema s1; >> create publication pub2 for table t_1(b); >> >> ----sub >> - prepare tables >> CREATE SUBSCRIPTION sub CONNECTION 'port=10000 dbname=postgres' PUBLICATION pub1, pub2; >> >> When doing table sync for 't_1', the column list will be (b). I think it should >> be no filter because table t_1 is also published via ALL TABLES IN SCHMEA >> publication. >> >> For Row Filter, it will use no filter for this case. >> >> >> 2) one publication publishes both parent and child >> ----pub >> create table t (a int, b int, c int) partition by range (a); >> create table t_1 partition of t for values from (1) to (10) >> partition by range (a); >> create table t_2 partition of t_1 for values from (1) to (10); >> >> create publication pub2 for table t_1(a), t_2 >> with (PUBLISH_VIA_PARTITION_ROOT); >> >> ----sub >> - prepare tables >> CREATE SUBSCRIPTION sub CONNECTION 'port=10000 dbname=postgres' PUBLICATION pub2; >> >> When doing table sync for table 't_1', it has no column list. I think the >> expected column list is (a). >> >> For Row Filter, it will use the row filter of the top most parent table(t_1) in >> this case. >> >> >> 3) one publication publishes both parent and child >> ----pub >> create table t (a int, b int, c int) partition by range (a); >> create table t_1 partition of t for values from (1) to (10) >> partition by range (a); >> create table t_2 partition of t_1 for values from (1) to (10); >> >> create publication pub2 for table t_1(a), t_2(b) >> with (PUBLISH_VIA_PARTITION_ROOT); >> >> ----sub >> - prepare tables >> CREATE SUBSCRIPTION sub CONNECTION 'port=10000 dbname=postgres' PUBLICATION pub2; >> >> When doing table sync for table 't_1', the column list would be (a, b). I think >> the expected column list is (a). >> >> For Row Filter, it will use the row filter of the top most parent table(t_1) in >> this case. >> > > Attached is an updated patch version, addressing all of those issues. > > 0001 is a bugfix, reworking how we calculate publish_as_relid. The old > approach was unstable with multiple publications, giving different > results depending on order of the publications. This should be > backpatched into PG13 where publish_via_partition_root was introduced, I > think. > > 0002 is the main patch, merging the changes proposed by Peter and fixing > the issues reported here. In most cases this means adopting the code > used for row filters, and perhaps simplifying it a bit. > > > But I also tried to implement a row-filter test for 0001, and I'm not > sure I understand the behavior I observe. Consider this: > > -- a chain of 3 partitions (on both publisher and subscriber) > CREATE TABLE test_part_rf (a int primary key, b int, c int) > PARTITION BY LIST (a); > > CREATE TABLE test_part_rf_1 > PARTITION OF test_part_rf FOR VALUES IN (1,2,3,4,5) > PARTITION BY LIST (a); > > CREATE TABLE test_part_rf_2 > PARTITION OF test_part_rf_1 FOR VALUES IN (1,2,3,4,5); > > -- initial data > INSERT INTO test_part_rf VALUES (1, 5, 100); > INSERT INTO test_part_rf VALUES (2, 15, 200); > > -- two publications, each adding a different partition > CREATE PUBLICATION test_pub_part_1 FOR TABLE test_part_rf_1 > WHERE (b < 10) WITH (publish_via_partition_root); > > CREATE PUBLICATION test_pub_part_2 FOR TABLE test_part_rf_2 > WHERE (b > 10) WITH (publish_via_partition_root); > > -- now create the subscription (also try opposite ordering) > CREATE SUBSCRIPTION test_part_sub CONNECTION '...' > PUBLICATION test_pub_part_1, test_pub_part_2; > > -- wait for sync > > -- inert some more data > INSERT INTO test_part_rf VALUES (3, 6, 300); > INSERT INTO test_part_rf VALUES (4, 16, 400); > > -- wait for catchup > > Now, based on the discussion here, my expectation is that we'll use the > row filter from the top-most ancestor in any publication, which in this > case is test_part_rf_1. Hence the filter should be (b < 10). > > So I'd expect these rows to be replicated: > > 1,5,100 > 3,6,300 > > But that's not what I get, unfortunately. I get different results, > depending on the order of publications: > > 1) test_pub_part_1, test_pub_part_2 > > 1|5|100 > 2|15|200 > 3|6|300 > 4|16|400 > > 2) test_pub_part_2, test_pub_part_1 > > 3|6|300 > 4|16|400 > > That seems pretty bizarre, because it either means we're not enforcing > any filter or some strange combination of filters (notice that for (2) > we skip/replicate rows matching either filter). > > I have to be missing something important, but this seems confusing. > There's a patch adding a simple test case to 028_row_filter.sql (named > .txt, so as not to confuse cfbot). > FWIW I think the reason is pretty simple - pgoutput_row_filter_init is broken. It assumes you can just do this rftuple = SearchSysCache2(PUBLICATIONRELMAP, ObjectIdGetDatum(entry->publish_as_relid), ObjectIdGetDatum(pub->oid)); if (HeapTupleIsValid(rftuple)) { /* Null indicates no filter. */ rfdatum = SysCacheGetAttr(PUBLICATIONRELMAP, rftuple, Anum_pg_publication_rel_prqual, &pub_no_filter); } else { pub_no_filter = true; } and pub_no_filter=true means there's no filter at all. Which is nonsense, because we're using publish_as_relid here - the publication may not include this particular ancestor, in which case we need to just ignore this publication. So yeah, this needs to be reworked. regards -- Tomas Vondra EnterpriseDB: http://www.enterprisedb.com The Enterprise PostgreSQL Company