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 1wFPEQ-0053vU-37 for pgsql-hackers@arkaria.postgresql.org; Wed, 22 Apr 2026 04:30:35 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wFPEP-00BleG-0N for pgsql-hackers@arkaria.postgresql.org; Wed, 22 Apr 2026 04:30:33 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wFPBM-00Biqb-0X for pgsql-hackers@lists.postgresql.org; Wed, 22 Apr 2026 04:27:24 +0000 Received: from mail-pj1-x1030.google.com ([2607:f8b0:4864:20::1030]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wFPBK-00000002C8w-09Ai for pgsql-hackers@lists.postgresql.org; Wed, 22 Apr 2026 04:27:23 +0000 Received: by mail-pj1-x1030.google.com with SMTP id 98e67ed59e1d1-35da1af3e10so4762484a91.3 for ; Tue, 21 Apr 2026 21:27:22 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1776832041; cv=none; d=google.com; s=arc-20240605; b=ORL/TTLA+uXPFRAwLlwkPcu/Ee0ptqrrn2zWjG3vsgThkpeky3vV7B1De+n2kUvcut B2oVzkLy01CRiOeCLm5mYn4omu/NvRUIpCzwxIB1VgAl1Bafaut6+GWrU2zq5olXglgo xIy9btV66UW6b9b10UY+nWG/yaJat07JCESDOmlVopUWwwwuQmXRnw0H8wWwZuRxf6Gv q0YnwoXQKy0CXlUXEKbNaAwzn0upNKVfj6+oFFUpMB+5bDpyjIXV6h65dHXlpUSUxlpu 4f+2YcpU7fCZkb43XK+eAIpNzEUPW94mjBvikWiVV/wZNOY8B0dbDRXW2YQSciSzHEHW s0iA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:dkim-signature; bh=czVCNH9T25oKULFI3ixLb93Dfoas4upoCOb0wsnEriM=; fh=9C3DpmTKTYdguDoqEOwFOVk1A3BBKddmBNSB7qgXPnw=; b=Krr1QUN3nr8vfE8l5qD8s0PGim3b8aZaASg4vsoVUXD4HZwXUWi+KGDjgfBkMy1ZuK 8glXJwuw53quw5zqpvLytiKI3pVcAfq+mRPsFHcT812uF1MlAyplYSOAAUObcebAsVYq bjK26hkbMyagkMcYXKcdx1tqfeAOn53XR21r7ULzf5LwLUofTsG9WE8EhVDmKkbtIu88 mHatkYPEfDdE3tzZpOfiLjWkGeT1muqZmleT0p2lOPOGSgaN/LZ5SODGm0AYnBeUQ9d+ pBWlaZDtSZJNjOVg3wRCTqE+5qy3ibnJxnR9P9blXBmuDiPR2z/Lb6zTvlnrrhohMgby f7FA==; darn=lists.postgresql.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776832041; x=1777436841; darn=lists.postgresql.org; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=czVCNH9T25oKULFI3ixLb93Dfoas4upoCOb0wsnEriM=; b=bWGnDM7XYfGY9JzKy8IizUbnEi776ZexnkgcbyjZ7q0JDbqzeJUqdypmoJf3R8h8L0 8Ibb3F3foSxnvEt66AVDRN3Q9VtElZXBd5ksRT8toV0sgw2f6mFbVFdsUrnCwLhrOQBf 8r15q+fiURVWtIdSECbtqxA2VO/zUyrPfPoStOx4NtBkk10wFDnYTo/iX/bYkqxrsj8N 0qSsRr2OshcXtJBXDmiiMLE0Yol7fCGFOVXFjTjAqHVTWCjQN2zf0s50LwkKpZs1rePV zcn6SdRftfDITUHvrzpgXj2jY1efA5axqjkjBwhM7FNl3svmAoPLRWUh6Nvvb1N/RLTR r/vA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776832041; x=1777436841; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=czVCNH9T25oKULFI3ixLb93Dfoas4upoCOb0wsnEriM=; b=kXOdoh4Da5UOU0a0DUdmRCk8h7QCuA2/p7SzCdRJp9l9K292XsUU4lO2WtlR6w92jb 25ruiQzs/V6nJmeOz/yqwdvsQU+6f1ZZ5fc4zfN4VZyPHE21cuwHCJKXn90QqXoQMpKh 8x9LrP6IkyxVprihXmi9GYnAvMSrBq69bVDkOreIMkqL5PPDFGf7gUd2ExtCDcvBGZ9R HIbP8pVGoVUMO8Lw3dlrt4ufBFp4aPwZ640f0x0mRlkTxJgUHmDTC+AQ8LT2Tk1dMZU8 VwlGlkJLvqgkBdNPTezov4psImydxBk83V6nB6jO7kZ4o7+zmfQk9xSZoePjNn6B7iGp fnLg== X-Gm-Message-State: AOJu0YykI+WBh5MyD5VRxrE/V152T/ahSbFFB9vmG3f/OFUEVnDqfcv+ 2+O9mZ+EddmmwsMe/Gq9mp3x2fSG6UFOvMvANk7kR3MgCRoCMLKQMI27Wx1EwLA1qcTJkyDNcWO CZxZRax6wv1U1HQB2zg5ImzjCuI3IMciRmTu/W1o= X-Gm-Gg: AeBDievufU4AeQscjBDaLUG4QgKMj6/YXjQV8rUWdpWEx21AzTdIPI2t9Lee0BKzbts jZkt/2iRTQ/lCa/L94/Ver534aXhVBmwnHcBmWqpWyZ4wyslq+0OCl6WeUGWmhyp8ulY34oLCRe LjQOK8nuUR/BWY2L0ZD7kX5iK5ti2xtRXtmStibqT1EncksIGqXgcyTNz49uPTwDkFCtwsA0BFl rwG6dDdBiZfEFIHGpIBji6Pf8cAuBB52u6GHF9zF4pADCmvqMRyhD8XK4kT2bqZr+dOfCt6nI7m h/TYrkGGuU7IcyIDWkE3t0W+jZZ7j/J6H0KG+xJSlUR+qxEw4amciMlb87HLiNor X-Received: by 2002:a17:90b:1dc9:b0:35b:e551:e776 with SMTP id 98e67ed59e1d1-361404a6c39mr20056057a91.27.1776832041517; Tue, 21 Apr 2026 21:27:21 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: shveta malik Date: Wed, 22 Apr 2026 09:57:10 +0530 X-Gm-Features: AQROBzCmgXHjQ0TxunOLqsTMD9UBKVgcFR6ipWpQXF-MesfpmM0_ddJUat_D90M Message-ID: Subject: Re: Fix pg_upgrade to detect invalid logical replication slots on PG19 To: Lakshmi N , Sawada Masahiko Cc: "pgsql-hackers@lists.postgresql.org" , shveta malik Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Mon, Apr 20, 2026 at 2:28=E2=80=AFPM Lakshmi N = wrote: > > Hi Hackers, > > The PG19-optimized slot catchup query uses a CTE that filters on > invalidation_reason IS NULL, then cross-joins it with the main slot > query. When ALL logical slots in a database are invalid, the CTE > returns zero rows, and the cross join produces an empty result set. > This causes pg_upgrade to silently skip those slots entirely -- > neither detecting them as invalid (which should block the upgrade) > nor attempting to migrate them. > > The pre-PG19 query path does not have this problem because it queries > pg_replication_slots directly without a cross join. This may not impact > upgrade to PG19 but will change the behavior for PG20 upgrade. > > Fix by changing the cross join to a LEFT JOIN, > so that invalid slots still appear in the result set with NULL > caught_up values. > I agree with the problem here. Another way to solve this would be using a scalar subquery(see [1]), but that would reduce readability. Thus, I prefer a LEFT OUTER JOIN on TRUE here. There should also be no performance impact, since the right-hand side query will always return at most one row due to the LIMIT 1 clause. So IMO, the proposed solution is good. Copying Sawada-san, as he was the author of the original patch. [1]: SELECT slot_name, plugin, two_phase, failover, CASE WHEN invalidation_reason IS NOT NULL THEN FALSE ELSE ( (SELECT last_pending_wal FROM check_caught_up) IS NULL OR confirmed_flush_lsn > (SELECT last_pending_wal FROM check_caught_up) ) END as caught_up, invalidation_reason IS NOT NULL as invalid FROM pg_catalog.pg_replication_slots WHERE slot_type =3D 'logical' AND database =3D current_database() AND temporary IS FALSE; thanks Shveta