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 1vnZUH-008xwf-0U for pgsql-hackers@arkaria.postgresql.org; Wed, 04 Feb 2026 09:47:53 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vnZUG-00AHY3-0K for pgsql-hackers@arkaria.postgresql.org; Wed, 04 Feb 2026 09:47:51 +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 1vnZUF-00AHXu-2b for pgsql-hackers@lists.postgresql.org; Wed, 04 Feb 2026 09:47:51 +0000 Received: from mail-oo1-xc2b.google.com ([2607:f8b0:4864:20::c2b]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1vnZUD-00000000VAq-1QzO for pgsql-hackers@lists.postgresql.org; Wed, 04 Feb 2026 09:47:50 +0000 Received: by mail-oo1-xc2b.google.com with SMTP id 006d021491bc7-66314fa03c9so2971263eaf.2 for ; Wed, 04 Feb 2026 01:47:49 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1770198468; cv=none; d=google.com; s=arc-20240605; b=f4O93/0ITsbdUYqDleEFcquQ7xaumAJxzEIkuYKSJgXxYLPxeFzqFqga6gbJDKkxZD ebRNx8T/4PeIGJyVeukAZXKEwdmVrw/cI4wNwjKpbDF767t5tZb35AkUb8m1GdeRLF26 eMYgkaX0w7pGs7Ck+iCQFckBUQhT8igZBZovMHj3/iYNbdt8vF9bj4p7frJfdIDJiUC3 Cwbkq3OjCju4ToxC8wAsyBOKyYp4oKh4DgTHD6xtLpgnZUMJVWyxdZUfZDoaW3yoau8B Udblr4CGuc6Y2ehuV3fFak4K81BTItzTuVYl0O6SPdvzaSZmJfrDKZZUfiWB5LduJCGV wNbg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=content-transfer-encoding:to:subject:message-id:date:from :in-reply-to:references:mime-version:dkim-signature; bh=N9fWp78q25H6b6VAtJ0iDZNSKdvLO767ZyEIEgL8zcM=; fh=pmBMntjmyx6XYOkmIq7jCPL8+6Ex8nEv6KGKxj4+8uc=; b=UyBFf/CxYDTFolKiSURBMXSZ7MRMnivlNb5tc8OMXtVvVEQTMjMBoEqMLZbrjdLxch o3XxUxDXxcHsvok2MIKniqFi76jApCNK9FQWzZ2C8W2o+w/jqfvKJozWsaJLfM3BhVmE n9a175nd4s7vySItu2rfiSpxhB4RIH2rfGs/QTOZKi2Gw1vwcNK2tGHwDMtFId75HGWW ZQu5LgQxVI1BMuQgjOmV1IF1lhDxFEeUCSKWnWuTtOGGTGnBry2ql+NpW0Emo0tsYOi9 QGmi/1u4sTWA2Q7sk/QuyjiiRyUC53ZdhO2JZyZ7yweLT3Bo+dTfn/tEknRSKCLJZIDW zkrA==; 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=20230601; t=1770198468; x=1770803268; darn=lists.postgresql.org; h=content-transfer-encoding:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=N9fWp78q25H6b6VAtJ0iDZNSKdvLO767ZyEIEgL8zcM=; b=JKAAzul6VQcZ7kGHNjjwGjAST/Q1gEucJtLdZTKXGj388QAZGnGYDi9Ku54liF08/I 8acl+zQMeL/52BqK1j4fy0o1F1DSS9GpmbplHJzZ+zXlliEBcWBh1pnT1E1JOmYPKLNu 1G6Ngyf3l2aO+sCoK/pkhtPV0lik34vGIeBTTQRujyjvCmmvKedimoJp0ho2304rk/sO 5UI06jaNAz2XgZj+UGGtgs5JOnuNJvVRp/vzZ86nVUimhz4eGH6r18WszlaHFEMt1ROF LdLUn9UMwYLVtuPY6+Zr2c4qGFh2jmUYEE1vvCF85hD42sFUXeEuOcKCI3r3T+NcuPDh ZSIA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770198468; x=1770803268; h=content-transfer-encoding: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=N9fWp78q25H6b6VAtJ0iDZNSKdvLO767ZyEIEgL8zcM=; b=AgK74w1ILQcl3yUEhN++x4bS5uz5E5DWcLnypWFe5XHFcIIn4ZU2vW5P0nHnESUozY UDcOW9JDqvtov4bdDLS1LH8mBNdXzm9zf72VDiO5o3E/FvpDkcLIaQWLTqMOKzGfMA7n D+1LqAj3hthx/1QoTi/0ZqFvo/eGRWzi9+gz4onUUv0NT8ckOzkLbHhE75elM5FOz282 VbvPuOEqeNvN4evr0MLNvYJqgeZB9m8nQjDJ/ObfjamYsqxFF3lbaulPeOGpTbh5pCf9 nc+XqOo5UBxUGZI0DsAVrk2jwOiwh453t6WjmO7emoBoAHfP/n5D6zaJadqEsj/7mwey kHwA== X-Gm-Message-State: AOJu0Yxuiy4pVRAV0eKsdqV5Wliy3OxTBuL+8pfnlDErU6ecbwp4Dda3 TjqB6RLJ5vfeM3l0y+xAe2KIXvGZsJ1WxbCPLjc3mhjmhClMDV+4sXZMD5fZCoyRXOWA6T5Zc/B x8+/y75OGUt3Wyb0PXsf5bJHXreMhvVk/OJfH X-Gm-Gg: AZuq6aJNmXFzk6qAtZhcLBidPbYek5o/OhqbQcTdw4fYlvYGl3BlcpEUEAaCoZxcD9e K1EK7pVQfApPt5rapDCOrFu47tEmvOxbvBNLiAHzDp2bA1nOkpLCAdcLUQWHicAK0mU5KmjTN7H iagWqQ9+FEpcKxJyEpFuqkUHQbBT1HNWbucR3pq9dxAVf26x5aitDAxydgEaxLlhAGeqwDh/NkO FGzxRgO8ruprTBL12Cq5vcCiD1bft7iI0CPgUI6GDS4g2wXT6/SYy+Nor8qHeblA1ywCnvsJg== X-Received: by 2002:a05:6820:82c:b0:667:6da8:fc2d with SMTP id 006d021491bc7-66a2268eb6amr1220469eaf.42.1770198468491; Wed, 04 Feb 2026 01:47:48 -0800 (PST) MIME-Version: 1.0 References: In-Reply-To: From: Richard Guo Date: Wed, 4 Feb 2026 18:47:37 +0900 X-Gm-Features: AZwV_Qhtuti_Bmsb-0-JoqGAF4HeOz3-4xkwc8VGXUDf5ismqX-m-XA4r8GOj_c Message-ID: Subject: Re: Convert NOT IN sublinks to anti-joins when safe To: Pg Hackers 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 Tue, Feb 3, 2026 at 4:12=E2=80=AFPM Richard Guo = wrote: > This topic has been discussed several times in the past. Due to the > semantic mismatch regarding NULL handling, NOT IN is not ordinarily > equivalent to an anti-join. However, if we can prove that neither the > outer expressions nor the subquery outputs can yield NULL values, it > should be safe to convert NOT IN to an anti-join. I've noticed a loose end in the v1 patch. The semantic gap between NOT IN and anti-join actually exists whenever the operator returns NULL. For NOT IN, if (A op B) returns NULL, then NOT (NULL) evaluates to NULL (effectively false), and the row is discarded. In contrast, for an anti-join, if (A op B) returns NULL, it implies no match was found, and the anti-join logic dictates that the row should be kept. To guarantee that (A op B) never returns NULL, the current patch verifies that both A and B are non-nullable. However, this is not sufficient. The "op" might be an operator that returns NULL on non-null inputs. On the other hand, if "op" does not return NULL on NULL inputs, like IS DISTINCT FROM, we technically would not even need to require that A and B are non-nullable. Is there a convenient way to verify that an operator never returns NULL on non-null inputs? Would it be sufficient to insist that the operator belongs to btree opclass (assuming that the strict ordering requirements of btree imply this safety)? And, is it worth checking if an operator never returns NULL even on NULL inputs? If we can identify such operators, we should be able to remove the requirement that both sides of NOT IN must be non-nullable. Is there a convenient way to check for such operators? - Richard