Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wDnFX-003NIE-0b for pgsql-hackers@arkaria.postgresql.org; Fri, 17 Apr 2026 17:45:03 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wDnFW-00AlPS-1J for pgsql-hackers@arkaria.postgresql.org; Fri, 17 Apr 2026 17:45:02 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wDnFW-00AlPJ-0N for pgsql-hackers@lists.postgresql.org; Fri, 17 Apr 2026 17:45:02 +0000 Received: from mail-pl1-x62a.google.com ([2607:f8b0:4864:20::62a]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wDnFU-00000001gxq-0Ig5 for pgsql-hackers@lists.postgresql.org; Fri, 17 Apr 2026 17:45:01 +0000 Received: by mail-pl1-x62a.google.com with SMTP id d9443c01a7336-2a3e79fe2b8so907365ad.1 for ; Fri, 17 Apr 2026 10:44:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776447898; x=1777052698; darn=lists.postgresql.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=98XbZm7+P1N9vfAEU/q+eqsTtfa7oUToVtk8NmVacKY=; b=OUNMG7YCAhzzB4aZMgs+lsj08Ju7gfcWw5FvW1IvWHStGFpb/6poatLJ+biSfy8X+w dv9UansqvuQGiadv2yEzt1Y/FEqqlU2fjBznko29DRx9Np8s0jv5gJWPh5s+D2TNri4h q3P/XD/SN32wLomXxVUhzRHB8pTNaTIVXMXzUOvw3tA9j8ZJJB8QGJbbeaiEK6FgsXJ7 ZRZhR9xloeYK6gk0H5gKaYG4+TgySXSQgNraADxPm1RaarpzVmUmWemCKOD+H42Rkf8U VvP05/HdzY3b5Xue69/wG5yoie0IOQeYqjYjCngOgKtH0dhw+cu5DdEmgX+m6qlf7MkQ ZokQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776447898; x=1777052698; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=98XbZm7+P1N9vfAEU/q+eqsTtfa7oUToVtk8NmVacKY=; b=NEqX2lk5PJtfRIm0ghhkssth0WCpzc5uPjTT8ZkY5lMbpS9K3fONy9AjURY9r+Bc+2 SC1T2rIcaY+HGdDHCBGGRepkuQ30Myoe1k2ID9sVy1u081F8roP3mPpx+XmCODgPE2X3 u8roDzigfsSwSZN+PZzyt4voGcof3FxO2VAxHjE8hMaa51lex58UVTygx5JWKAiaW00x 6+13sIoI1MdNjKqaqqwsqvugSDUCAHnn8tn1/OXNw4yIQLPoMEvmEVOS0vHQXhKdpJ5Y VtSRmKGM2KzR877inVF/2FP/1bdLcUo8GjJInuio/EID/xmd/FN1bjVLetbOp/UoeGwa /h4A== X-Gm-Message-State: AOJu0YzQ56RBzvnU957eXNGFlQVZAqW89sjMheoy2bAza8f7Q4ZIQ+Ai P4TgYMAJAFFjiFzekthxveIgElSpnHWcKw0tM4gwsPupji10PyPK/o95fQn4hGSC X-Gm-Gg: AeBDievUCVkg52cMFktieU2U7QKHvzTi4+ghrK55VkMHrCE8P6vcTAPrKdBv4MSQdQj ND2MZoG45Np5a3kYWTXuNqWm1BXg444SIfyIKE7Osqac3nIEYDu2RYM7vTkApqgdRBygzYzeq9+ WKhZXzAKkzT/cd6bs4WmDXM7p9FEkOu6jnk61M06680rN4nXsl6yQ32wTHsgaDsOn4IBRkmPif0 ie/GNRbeGkldv6274uH7vdlITN6Ehk5zAAZO2dfW7Wrz+pQUBbe/TayJi3Q1877msGXXLqoRn+l y6Dbs7hokSgx4GMpAxoMkj07dkDhM8IemHSOGPz5S4CE7veDjqrFdIO0+EvK2F9lFelnnM3M03y tg7CHe2Ux73QM2l6luaBocEzqMkoxN1lSDZQl3V35RNXqOmnK0UANcUXY5rCtyucEb0kwoCKx27 RLr60jlyD1otI1jXSHwZMzkpCmhEU= X-Received: by 2002:a17:903:390f:b0:2b0:4d92:b8c7 with SMTP id d9443c01a7336-2b5f9e79f9dmr24048855ad.1.1776447897815; Fri, 17 Apr 2026 10:44:57 -0700 (PDT) Received: from ser8.. ([221.156.231.192]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2b5fa9fef42sm24860345ad.16.2026.04.17.10.44.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 17 Apr 2026 10:44:57 -0700 (PDT) From: DaeMyung Kang To: pgsql-hackers@lists.postgresql.org Cc: DaeMyung Kang Subject: [PATCH] Use direct hash lookup in logicalrep_partmap_invalidate_cb() Date: Sat, 18 Apr 2026 02:44:50 +0900 Message-ID: <20260417174450.4158878-1-charsyam@gmail.com> X-Mailer: git-send-email 2.43.0 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------2.43.0" Content-Transfer-Encoding: 8bit List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk This is a multi-part message in MIME format. --------------2.43.0 Content-Type: text/plain; charset=UTF-8; format=fixed Content-Transfer-Encoding: 8bit LogicalRepPartMap is keyed by the partition's OID, which is assigned to entry->relmapentry.localreloid when the entry is populated in logicalrep_partition_open(). The invalidation callback therefore does not need to iterate over every entry to find the one matching the invalidated relation OID; a single hash_search(HASH_FIND) on reloid suffices. This replaces an O(N) hash_seq_search loop with an O(1) lookup and removes the longstanding "TODO, use inverse lookup hashtable?" comment. An Assert in logicalrep_partition_open() documents the partOid == entry->relmapentry.localreloid invariant that the new path relies on. --- Tested on an --enable-cassert build: the full src/test/subscription TAP suite (39 files, 579 tests) passes, including 013_partition.pl which exercises the partmap invalidation path via ADD COLUMN on a partitioned root (cascades a relcache inval to every leaf partition). src/backend/replication/logical/relation.c | 23 +++++++++------------- 1 file changed, 9 insertions(+), 14 deletions(-) --------------2.43.0 Content-Type: text/x-patch; name="0001-Use-direct-hash-lookup-in-logicalrep_partmap_invalid.patch" Content-Transfer-Encoding: 8bit Content-Disposition: attachment; filename="0001-Use-direct-hash-lookup-in-logicalrep_partmap_invalid.patch" diff --git a/src/backend/replication/logical/relation.c b/src/backend/replication/logical/relation.c index 0b1d80b5b0f..f6e2a9a6422 100644 --- a/src/backend/replication/logical/relation.c +++ b/src/backend/replication/logical/relation.c @@ -544,20 +544,14 @@ logicalrep_partmap_invalidate_cb(Datum arg, Oid reloid) if (reloid != InvalidOid) { - HASH_SEQ_STATUS status; - - hash_seq_init(&status, LogicalRepPartMap); - - /* TODO, use inverse lookup hashtable? */ - while ((entry = (LogicalRepPartMapEntry *) hash_seq_search(&status)) != NULL) - { - if (entry->relmapentry.localreloid == reloid) - { - entry->relmapentry.localrelvalid = false; - hash_seq_term(&status); - break; - } - } + /* + * LogicalRepPartMap is keyed by partition OID, which matches + * entry->relmapentry.localreloid (see logicalrep_partition_open), so + * we can invalidate via a direct hash lookup. + */ + entry = hash_search(LogicalRepPartMap, &reloid, HASH_FIND, NULL); + if (entry != NULL) + entry->relmapentry.localrelvalid = false; } else { @@ -676,6 +670,7 @@ logicalrep_partition_open(LogicalRepRelMapEntry *root, */ if (found && entry->localrelvalid) { + Assert(entry->localreloid == partOid); entry->localrel = partrel; return entry; } --------------2.43.0--