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 1vdcTL-002qcF-0o for pgsql-general@arkaria.postgresql.org; Wed, 07 Jan 2026 22:57:48 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vdcTI-00FyxS-0u for pgsql-general@arkaria.postgresql.org; Wed, 07 Jan 2026 22:57:45 +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 1vdcTH-00FyxK-2z for pgsql-general@lists.postgresql.org; Wed, 07 Jan 2026 22:57:44 +0000 Received: from mail-ej1-x634.google.com ([2a00:1450:4864:20::634]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1vdcTF-005A2U-2c for pgsql-general@lists.postgresql.org; Wed, 07 Jan 2026 22:57:44 +0000 Received: by mail-ej1-x634.google.com with SMTP id a640c23a62f3a-b7a72874af1so487636866b.3 for ; Wed, 07 Jan 2026 14:57:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1767826660; x=1768431460; darn=lists.postgresql.org; h=to:subject:message-id:date:from:mime-version:from:to:cc:subject :date:message-id:reply-to; bh=fgx4xCLYs2D3lx5bPeRAL2LliYzBIZgXdpWKAIyLRgs=; b=fTRJRg17BLoCeIRtxB4i9KOpa3WNmH9lVrCQMMkEQnBvREzeGk+tNUSEaC/ysPtfr3 xBH4Dii5X33UIJwMexQPhf1XDDrwVn9PEnqDEePyBqzATz5/ROISzi0/QofU/oYkVSdY IOyLEoGUzlq2iKkv5faJ473wvWuqpRp2Py8tfpfQhWR6dw6IFg9FtT3AFh4QsxhgBKDJ IOmTxyYbJ+w8rO3gG08UmcLZIHTkoURFCpSaj7XeeSRsoTobxBQdEHO7k1THsJ199Br8 3EmxLnP3Dw1so1XduJvjhvXl7zGbtKx5amczJME8czSmil+OS+z566XSLXzByeSWtCCh ATdg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767826660; x=1768431460; h=to:subject:message-id:date:from:mime-version:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=fgx4xCLYs2D3lx5bPeRAL2LliYzBIZgXdpWKAIyLRgs=; b=LNnT6rYBFLJSFInjd9NlMxuyIpZ91PpY4BiKVYNPI9b2pLCZij6g1e1ROcqs1ieT+Z JsVsbM8HED3+B5qvg4zCjnVJXBZfdUDn1vpdfNzg724/QAabpZsaXom6bYG7qoF8CUJ5 S9GXWsS3eN5yJr3Aos13e6mmam72UYJipq9W6dZ6DQR9wRj/cYij2/da9p01WSoZ0+hF fZ3FMfimW5/gn3yA/wlpiVv9PkxOFXYA4/oGuA9uZlmJirf8ELXSEI4MmRDg0IFFnPan zhqoJfECrrB46nBPKjaKO8C0cstJkPvIyYUU4OuwRGGbtRianqyjZD8JQMHF/TMBgITd ayQg== X-Gm-Message-State: AOJu0Yx88MWuve0up1y5Q9MX2tF8diHvJK1x3YfibGWtjKvViITbwML4 QVHYoBwLW3LaanRD2VIiRl5/7ToJxQXNjh7fdXCiGWn0L/Kr8SdUItX+6aFnx5kIEGCOd/yJpiI xclEWQQtm1iNK3P2UdINZIbeYw46V/nUw8t/k X-Gm-Gg: AY/fxX7/26X40WBLzJ6JlPPz/Pt/iCb5WN+SIlHppN3RAZ1yLaMjZ0Eu0tCQ+hgQoLI NaWwPkjFrmPcb0HpxsmZdzMztOm9JOO+eMMlNNDH5wAY8S1PyKAMGjkYQ5DIqSif5bnmAoLLVwH fjwjLzcuVaaqhy2mCq3NYmrJ2MK5bobw6a4I7u7mW7XWysJYrKhz9+HdX7c/UVae/bnTXQn8YeS GiqygMhBTMZSyqTaDegiUaOx8zQtriOPGUMumsKZqtKLbGTuFxPpl43zrdLVeqImd5v78k2fokM cVJEk16AsVU8+wwH2RtJhISdOH4= X-Google-Smtp-Source: AGHT+IE23mXONid5pZ0MAdy0SrYCmSRQvXuvclAcRETk/+frhZDld621/CRqxtAaGEghCVyUzwZV7vReYs50MbBSRBA= X-Received: by 2002:a17:907:2d07:b0:b80:3fb7:102f with SMTP id a640c23a62f3a-b8444ce5658mr422237566b.28.1767826659957; Wed, 07 Jan 2026 14:57:39 -0800 (PST) MIME-Version: 1.0 From: Yuri Kutsko Date: Wed, 7 Jan 2026 14:57:27 -0800 X-Gm-Features: AQt7F2o80l9mUU5Tyds9oHpR1Xh3AS7HniLBM6W1QlbH4kBRF4Vo58w3oviqfU0 Message-ID: Subject: EXPLAIN(GENERIC_PLAN) failing for some queries To: pgsql-general@lists.postgresql.org Content-Type: multipart/alternative; boundary="000000000000175e4e0647d43846" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --000000000000175e4e0647d43846 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable I want to identify every query in my company=E2=80=99s database that potent= ially uses full table scans. To do this, I wrote a simple PL/pgSQL function that generates an execution plan for each query from pg_stat_statements and then searches the plan for the 'Seq Scan' pattern. Most queries contain parameters, so I use EXPLAIN (GENERIC_PLAN). This works for approximately 80% of queries, but it fails in the following scenarios: 1. Planner cannot infer parameter types without explicit casts The following fails: EXPLAIN (GENERIC_PLAN) SELECT * FROM tbl WHERE id =3D = $1 + $2; The following works: EXPLAIN (GENERIC_PLAN) SELECT * FROM tbl WHERE id =3D $1::integer + $2::integer; 2. Parameter is used in EXTRACT The following fails: EXPLAIN (GENERIC_PLAN) SELECT * FROM tbl WHERE EXTRACT($1 FROM date_col) =3D 1; The following works: EXPLAIN (GENERIC_PLAN) SELECT * FROM tbl WHERE date_part($1, date_col) =3D 1; 3. Parameter is used in type 'string' notation The following fails: EXPLAIN (GENERIC_PLAN) SELECT int $1; The following works: EXPLAIN (GENERIC_PLAN) SELECT $1::int; I modified my procedure to account for these scenarios, but I am not sure whether there are other issues with EXPLAIN (GENERIC_PLAN) that I am not aware of. Problem #1 is mentioned in the EXPLAIN documentation (https://www.postgresql.org/docs/18/sql-explain.html) at the bottom of the page, but the other cases are not. My questions are: Are all of the issues described above expected behavior for EXPLAIN (GENERIC_PLAN)? Are there other known scenarios where EXPLAIN (GENERIC_PLAN) will fail? Should the EXPLAIN documentation be updated to list scenarios in which EXPLAIN (GENERIC_PLAN) can fail? Yuri Kutsko --000000000000175e4e0647d43846 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
I want to identify every query in my company=E2=80=99s dat= abase that potentially uses full table scans.
To do this, I wrote a simp= le PL/pgSQL function that generates an execution plan for each query from p= g_stat_statements and then searches the plan for the 'Seq Scan' pat= tern.
Most queries contain parameters, so I use EXPLAIN (GENERIC_PLAN). = This works for approximately 80% of queries, but it fails in the following = scenarios:

1. Planner cannot infer parameter types without explicit = casts
The following fails: EXPLAIN (GENERIC_PLAN) SELECT * FROM tbl WHER= E id =3D $1 + $2;
The following works: EXPLAIN (GENERIC_PLAN) SELECT * F= ROM tbl WHERE id =3D $1::integer + $2::integer;

2. Parameter is used= in EXTRACT
The following fails: EXPLAIN (GENERIC_PLAN) SELECT * FROM tb= l WHERE EXTRACT($1 FROM date_col) =3D 1;
The following works: EXPLAIN (G= ENERIC_PLAN) SELECT * FROM tbl WHERE date_part($1, date_col) =3D 1;

= 3. Parameter is used in type 'string' notation
The following fai= ls: EXPLAIN (GENERIC_PLAN) SELECT int $1;
The following works: EXPLAIN (= GENERIC_PLAN) SELECT $1::int;

I modified my procedure to account for= these scenarios, but I am not sure whether there are other issues with EXP= LAIN (GENERIC_PLAN) that I am not aware of.
Problem #1 is mentioned in t= he EXPLAIN documentation
(https://www.postgresql.org/docs/18/sql-explain.html) = at the bottom of the page, but the other cases are not.
My questions are= :
Are all of the issues described above expected behavior for EXPLAIN (G= ENERIC_PLAN)?
Are there other known scenarios where EXPLAIN (GENERIC_PLA= N) will fail?
Should the EXPLAIN documentation be updated to list scenar= ios in which EXPLAIN (GENERIC_PLAN) can fail?
Yuri Kutsko
--000000000000175e4e0647d43846--