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 1tO7Vd-004FED-Nx for pgsql-general@arkaria.postgresql.org; Thu, 19 Dec 2024 03:47:34 +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 1tO7Vc-006HA1-1Q for pgsql-general@arkaria.postgresql.org; Thu, 19 Dec 2024 03:47:31 +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 1tO7Vb-006H9t-I0 for pgsql-general@lists.postgresql.org; Thu, 19 Dec 2024 03:47:31 +0000 Received: from mail-ed1-x534.google.com ([2a00:1450:4864:20::534]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1tO7VY-000JjT-Cl for pgsql-general@postgresql.org; Thu, 19 Dec 2024 03:47:29 +0000 Received: by mail-ed1-x534.google.com with SMTP id 4fb4d7f45d1cf-5d647d5df90so477825a12.2 for ; Wed, 18 Dec 2024 19:47:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=adriangb-com.20230601.gappssmtp.com; s=20230601; t=1734580046; x=1735184846; darn=postgresql.org; h=to:subject:message-id:date:from:mime-version:from:to:cc:subject :date:message-id:reply-to; bh=j93lRrPRRJE9pca4vdIBwQgB22zpNx8WeEKGgYUI0+s=; b=Pp3T38Nz7SqSKWxm6jUA2o0dgK2ntz3vhUqYWwvv8Qcnu3C98yfqNmXcSjduiOq/6x t66WZNRC3yE4QBwoD5rwmVPfJU5nwJbPPCoNrI7/+sS5Cv7DObqBLXnS7XkTKbzSXA1z poLlRcaecw2JUQU4JECsx6KSIMUGw5mXB/TWHWFho1g9daAoSLbsajgQhOMzCuuKmX8M ZQyA9VbgUHYkb6g6R83zTHM0hdImqG4WOYbebT2/O7cPMr1LVsq62Ou1L7U6xQZEGl/r r3+lx0nIg7gyCeU05wuVE9LWGy84bgQxEIBbhihnzsFZD/EzfUaayD0b+YwHHDxzBRBl O62w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1734580046; x=1735184846; h=to:subject:message-id:date:from:mime-version:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=j93lRrPRRJE9pca4vdIBwQgB22zpNx8WeEKGgYUI0+s=; b=H3Wk4Ux0l971PmMC3wXW08p1K6uoJSQ1pvA9POZo0LCKeVMdPTkW6CtWTcBH2wwLc0 BJrojrQ5QXuQcf3dYJzdgtpdXOxBI2fcbr5dJUouMxKY2ufp2m5eMyYsiMFEpg2RJRRG h70nrGKX6WOlkXeYGOLlJU0a+ulaNkmiaAap3p2tdjvRMObn2rJFhr7Yb7FQT0p4uoEN z+2p//zM2NcZHM53+qoxkhrzjM5knf4ApD6aeP9ORN8vR5B9ZiNI5WgwKFPu0QpWaxGC DhE561/2XF4LJbeqNf7CJK5b+KB2Pp5MBs+KuPFmAE85M/S3g/q51XT0YEPQdcWTXCYF cwzg== X-Gm-Message-State: AOJu0YxyneHEH9njWNSULmWTwVoDsUXRRnseaT7fnN0Z9gJwFwhIhEao /jmqWrg6EbSWxL8GEg2tRpxeUB8acVDR5XudLj87N3160zTlZWccPn7i8FP67bqLYLr/jcMzG6C CkP1my8111HJdpR0FfEetJitiuKL0Zj0NSR4jcllgDrbHYulXfYU= X-Gm-Gg: ASbGncsaNJ4zP7WeKaVUXHb2VmZmbo99fFitJ+i4gTLKayqwAr8VoWh+9bT7enibLdE 1956SXKPxB9uV5JUgN8h9dOsFhFsK40WyF65fCjRo X-Google-Smtp-Source: AGHT+IE00bGBKzERIbKeyNWPd/MoKmuGVLE7EsxUyWE1o85hXaMhPBBVFs2jWHFcZYMa05CzVMw7gPk1IMe0QVOZbpg= X-Received: by 2002:a05:6402:530e:b0:5d3:cdb3:a60 with SMTP id 4fb4d7f45d1cf-5d7ee4269d2mr4934416a12.34.1734580046277; Wed, 18 Dec 2024 19:47:26 -0800 (PST) MIME-Version: 1.0 From: Adrian Garcia Badaracco Date: Wed, 18 Dec 2024 21:47:15 -0600 Message-ID: Subject: Wrapping a where clause to preserve rows with nulls To: pgsql-general@postgresql.org Content-Type: multipart/alternative; boundary="0000000000007e78eb0629976344" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --0000000000007e78eb0629976344 Content-Type: text/plain; charset="UTF-8" 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 return `null`, but I actually want to keep rows that return `null` (and rows that 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 = 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 = 5000; But as soon as I tack on an `IS NOT FALSE` the index is not used: SELECT * FROM test_index WHERE (value = 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 null while still using an index? --0000000000007e78eb0629976344 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
I have a query where I have to run a where clause generate= d by another system (i.e., I can't modify that where=C2=A0clause. The w= here 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`f= alse`).

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:

<= /div>
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 t= o null while still using an index?

--0000000000007e78eb0629976344--