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.94.2) (envelope-from ) id 1tO7uA-004IDV-1C for pgsql-general@arkaria.postgresql.org; Thu, 19 Dec 2024 04:12:54 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1tO7u8-006WD9-Kp for pgsql-general@arkaria.postgresql.org; Thu, 19 Dec 2024 04:12:52 +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.94.2) (envelope-from ) id 1tO7u8-006WD0-9M for pgsql-general@lists.postgresql.org; Thu, 19 Dec 2024 04:12:52 +0000 Received: from mail-ej1-x62f.google.com ([2a00:1450:4864:20::62f]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1tO7u5-000Jsf-BJ for pgsql-general@postgresql.org; Thu, 19 Dec 2024 04:12:50 +0000 Received: by mail-ej1-x62f.google.com with SMTP id a640c23a62f3a-aa69077b93fso44057066b.0 for ; Wed, 18 Dec 2024 20:12:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=adriangb-com.20230601.gappssmtp.com; s=20230601; t=1734581567; x=1735186367; darn=postgresql.org; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :from:to:cc:subject:date:message-id:reply-to; bh=ffR+GrCNC2vQKxkLqURGwyQfZ/hHdtU1cG26NnOHMUI=; b=owK8whCPoEWZJEJa1DB0oMxKD32C6AzerXuYkYmc6hA0+b9VZukYEJHx4s8zGN6JzW NcKJ47/mo5NX2AT29aztAoycAx2JNZgyGXefVwXHOv4E6kzG64dAtqLUctjaW71gLFvx pe0EbPqpQhMfe27ISnso6WhDXAo4/FFTSskR2CwbKe8bju9FelBdGD/ulHI+oCJW15Ep qE40MX2Ra17QD+fCIEKnQer2q2rgJdZPp6UeXAnzod/CpwO8Ap6kZ9vGWNIqZVqhX1uJ nOIvMw2LJp69VISMyQKMDRwXqoeL9lWCpJhhHN5Qjcc+0nI8pqRdhVLfG0hDuKoR5rdP v/Bg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1734581567; x=1735186367; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=ffR+GrCNC2vQKxkLqURGwyQfZ/hHdtU1cG26NnOHMUI=; b=JCN6IfVGNu1kcKIFs87a6UgagxxoomHkX8hCqTQV6MrAE3d/I1IL1hPVWH+ua1YHw1 REw1SzP37TkUfHZFLkVz+GkwQEBLJ93G/scER2wHG8aD6v31qcrJDOYv3ilKdYijQ7KG DIMPkXmu2TxsZp8c5YAi5CJW9V2KHRR6i1RP86rGr7pSx/7D5fWXt2QaNl59+pWvvMZC BF2MWnqrlWF8ptM8SbhaMPBTBDpiUlibVpmmCZ2TxC2VF4A4AO7R7TNuhsShRKcqn44E qrCf0pFVOU58IC0TQdDEsIolHolm6bLkNgYagMLZfGSN4lBPRrjrl6kxMuSm1WQcMfb+ MndA== X-Gm-Message-State: AOJu0YzIyGJSIcNrmvlbt8GjqYTJUgwLadLCXjHxihy194qyWD9XlKq0 H9o8vv5byESaOBRxo8CNnLRrTHoi8b5WvjLcx8rlmkeMAwZozHi/d13o0yn/MLjc+5d6recTWWY WtDamnmdDTnYA8LnzHfIr/7RRi1wc0yHsbAT2c8FZNNEghhYq X-Gm-Gg: ASbGncuCud8xpv1RjuJ9DYIC6EYdPqR1V0VXKceWu1lWH7TjtIGxXs3cr3OhLY8O1Z4 BYoNn+UET+MCbzT+gBQwZBxhWPUD0+7JC/CyAOTIA X-Google-Smtp-Source: AGHT+IFRpod2PCLS6lAuW/o+22KHtNj3ENKCuKKkr2amzl+KisDSzur9ly76082/DDU7ps9tW9JUfeFtcZ2jUsOQun8= X-Received: by 2002:a17:907:980a:b0:aa6:90f1:a9bb with SMTP id a640c23a62f3a-aabf477f427mr409951166b.24.1734581566857; Wed, 18 Dec 2024 20:12:46 -0800 (PST) MIME-Version: 1.0 References: In-Reply-To: From: Adrian Garcia Badaracco Date: Wed, 18 Dec 2024 22:12:36 -0600 Message-ID: Subject: Re: Wrapping a where clause to preserve rows with nulls To: pgsql-general@postgresql.org Content-Type: multipart/alternative; boundary="000000000000208b7f062997be29" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --000000000000208b7f062997be29 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable I'll note that the clause is arbitrary in the sense that I don't generate it and cannot edit it but it's basically a bunch of boolean comparisons chained i.e. `col_a >=3D 1 and col_b <=3D5 and col_c ...` so I can in gener= al add an index on say col_a and it does get used. On Wed, Dec 18, 2024 at 9:47=E2=80=AFPM Adrian Garcia Badaracco wrote: > I have a query where I have to run a where clause generated by another > system (i.e., I can't modify that where clause. The where clause may retu= rn > `null`, but I actually want to keep rows that return `null` (and rows th= at > return `true` but not rows that return `false`). > > I thought it would be as simple as wrapping in `(...) is not false` but > that seems to prevent index usage. > > For example, let's say that given the table: > > CREATE TABLE test_index (value INTEGER); > CREATE INDEX idx_value ON test_index(value); > > And the predicate `value =3D 5000`, if I run the original query that > excludes rows where the predicate is null it uses the index: > > SELECT * > FROM test_index > WHERE value =3D 5000; > > But as soon as I tack on an `IS NOT FALSE` the index is not used: > > SELECT * > FROM test_index > WHERE (value =3D 5000) IS NOT FALSE; > > This was surprising to me. I was hoping this might be able to use the > index. > > Is there any way to include the rows where the predicate evaluates to nul= l > while still using an index? > > --000000000000208b7f062997be29 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
I'll note that the clause is arbitrary in the sense th= at I don't generate it and cannot edit it but it's basically a bunc= h of boolean comparisons chained i.e. `col_a >=3D 1 and col_b <=3D5 a= nd col_c ...` so I can in general add an index on say col_a and it does get= used.

On Wed, Dec 18, 2024 at 9:47=E2=80=AFPM Adria= n Garcia Badaracco <adrian@adrian= gb.com> wrote:
I have a query where I have to run a where clause ge= nerated by another system (i.e., I can't modify that where=C2=A0clause.= The where clause may return `null`,=C2=A0 but I actually want to keep rows= that return `null` (and rows that return `true` but not rows that return= =C2=A0`false`).

I thought it would be as simple as wrapp= ing in `(...) is not false` but that seems to prevent index usage.

For example, let's say that given the table:

CREATE TABLE test_index (value INTEGER);
CREATE INDEX id= x_value ON test_index(value);

And the predicate `v= alue =3D 5000`, if I run the original query that excludes rows where the pr= edicate is null it uses the index:

SELECT *
<= div>FROM test_index
WHERE value =3D 5000;

But as soon as I tack on an `IS NOT FALSE` the index is not used:
SELECT *
FROM test_index
WHERE (= value =3D 5000) IS NOT FALSE;

This was surpr= ising to me. I was hoping this might be able to use the index.
Is there any way to include the rows where the predicate evalu= ates to null while still using an index?

--000000000000208b7f062997be29--