pg.ddx.io  pgsql-bugs@postgresql.org mailing list archive  
help / color / mirror / Atom feed
BUG #19358: Short circuit optimization exists in generic plan but missed in custom plan
2+ messages / 2 participants
[nested] [flat]

* BUG #19358: Short circuit optimization exists in generic plan but missed in custom plan
@ 2025-12-17 12:03 PG Bug reporting form <noreply@postgresql.org>
  2025-12-17 21:37 ` Re: BUG #19358: Short circuit optimization exists in generic plan but missed in custom plan Tom Lane <tgl@sss.pgh.pa.us>
  0 siblings, 1 reply; 2+ messages in thread

From: PG Bug reporting form @ 2025-12-17 12:03 UTC (permalink / raw)
  To: pgsql-bugs@lists.postgresql.org; +Cc: 798604270@qq.com

The following bug has been logged on the website:

Bug reference:      19358
Logged by:          Chi Zhang
Email address:      798604270@qq.com
PostgreSQL version: 17.6
Operating system:   ubuntu 24.04 with docker
Description:        

Hi,

In the following test case, there are two equivalent updates; the first one
is in prepared form, and the second one is a normal update. There is a
configuration that sets plan_cache_mode = force_generic_plan, which means
the prepared updates will use a generic plan. When I run this test case, I
found the prepared update can execute, but the normal update triggers an
error `result of range difference would not be contiguous`, I can understand
this because this error is skipped in the prepared update by short circuit
optimization. As shown in the document at
https://www.postgresql.org/docs/current/runtime-config-query.html that, the
generic plan maybe inefficient than the custom plan. So why the short
circuit optimization applied in the prepared update (with a generic plan)
but not in the normal update (with a custom plan).

```
SET plan_cache_mode = force_generic_plan;
CREATE TABLE t3(c0 TEXT);
INSERT INTO t3(c0) VALUES('');
PREPARE prepare_query (text, int4range, int4range) AS UPDATE t3 SET c0=$1
WHERE (((t3.c0) IN (t3.c0))OR(((t3.c0)) BETWEEN (((t3.c0)||((($2)-($3)))))
AND (t3.c0)));
EXECUTE prepare_query('', '[-993693027,1525305818]'::int4range,
'[-168306621,-163656947)'::int4range);
DEALLOCATE prepare_query;
UPDATE t3 SET c0=''::text WHERE (((t3.c0) IN (t3.c0))OR(((t3.c0 )) BETWEEN
(((t3.c0)||((('[-993693027,1525305818]'::int4range)-('[-168306621,-163656947)'::int4range)))))
AND (t3.c0))); -- ERROR:  result of range difference would not be contiguous
```



^ permalink  raw  reply  [nested|flat] 2+ messages in thread

* Re: BUG #19358: Short circuit optimization exists in generic plan but missed in custom plan
  2025-12-17 12:03 BUG #19358: Short circuit optimization exists in generic plan but missed in custom plan PG Bug reporting form <noreply@postgresql.org>
@ 2025-12-17 21:37 ` Tom Lane <tgl@sss.pgh.pa.us>
  0 siblings, 0 replies; 2+ messages in thread

From: Tom Lane @ 2025-12-17 21:37 UTC (permalink / raw)
  To: 798604270@qq.com; +Cc: pgsql-bugs@lists.postgresql.org

PG Bug reporting form <noreply@postgresql.org> writes:
> ... So why the short
> circuit optimization applied in the prepared update (with a generic plan)
> but not in the normal update (with a custom plan).

Const-folding doesn't stop just because the current part of the
expression tree might not be reached at runtime.  EXPLAIN shows
that your generic plan is

regression=# explain verbose EXECUTE prepare_query('', '[-993693027,1525305818]'::int4range,
'[-168306621,-163656947)'::int4range);
                                             QUERY PLAN                                              
-----------------------------------------------------------------------------------------------------
 Update on public.t3  (cost=0.00..47.40 rows=0 width=0)
   ->  Seq Scan on public.t3  (cost=0.00..47.40 rows=157 width=38)
         Output: $1, ctid
         Filter: ((t3.c0 = t3.c0) OR ((t3.c0 >= (t3.c0 || (($2 - $3))::text)) AND (t3.c0 <= t3.c0)))
(4 rows)

So the "t3.c0 = t3.c0" condition will be found to be true and we don't
reach the right-hand side of the OR.  However, if $2 and $3 are
replaced by constants, the planner will attempt to reduce the range
difference to a constant at plan time.

There have been previous discussions about how this sometimes leads to
unintuitive failures, but I don't see how we could skip const-folding
without huge performance penalties in some cases.  In any case, we
clearly document that you can't rely on specific execution order of
boolean expressions.  You will not find anything in our docs promising
left-to-right evaluation of ORs.

			regards, tom lane





^ permalink  raw  reply  [nested|flat] 2+ messages in thread


end of thread, other threads:[~2025-12-17 21:37 UTC | newest]

Thread overview: 2+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2025-12-17 12:03 BUG #19358: Short circuit optimization exists in generic plan but missed in custom plan PG Bug reporting form <noreply@postgresql.org>
2025-12-17 21:37 ` Tom Lane <tgl@sss.pgh.pa.us>

This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox