Re: Non-Materialized CTE bug?

From: Kyotaro Horiguchi <horikyota(dot)ntt(at)gmail(dot)com>
To: greigwise(at)comcast(dot)net
Cc: pgsql-bugs(at)postgresql(dot)org
Subject: Re: Non-Materialized CTE bug?
Date: 2020-10-28 02:14:10
Message-ID: 20201028.111410.893088314257858562.horikyota.ntt@gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

Hello.

At Tue, 27 Oct 2020 17:43:08 -0700 (MST), greigwise <greigwise(at)comcast(dot)net> wrote in
> create table types (type varchar);
> CREATE TABLE
> insert into types values ('a');
>
> with test (i, j) as
> (values ( 1, '{"key": "a", "value": "true"}'::json), (2, '{"key": "b",
> "value": "xxx"}'::json)),
> test2 (i, j) as (select i, (j->>'value')::boolean
> from test a
> join types b on b.type = a.j->>'key') select * from test2 where j = true;
>
> ERROR: invalid input syntax for type boolean: "xxx"
>
> Why would this result in an error here? It seems like the second row from
> the "test" CTE should be excluded since the key value "b" will not join with
> anything in the "types" table. If I materialize the "test2" CTE, then it
> works as I'd expect without error. Is this a bug? It seems like the
> optimizer should be smart enough to know that it has to materialize that
> CTE. This is on version 12.4.

test2 needs to evaluate all the output columns *before* the join with
types, which leads to the error. You need to make sure that the
::boolean is evaluated after the join. MATERIALIZE prevents the CTE
from being merged into upper queries.

The following rewrites work.

with
test (i, j) as
(values ( 1, '{"key": "a", "value": "true"}'::json),
(2, '{"key": "b", "value": "xxx"}'::json)),
test2 (i, j) as MATERIALIZED
(select i, j->>'value' as j
from test a
join types b on b.type = a.j->>'key')
select i from test2 where j::boolean = true;

with
test (i, j) as
(values ( 1, '{"key": "a", "value": "true"}'::json),
(2, '{"key": "b", "value": "xxx"}'::json)),
test2 (i, j) as MATERIALIZED
(select i, j->>'value' as j
from test a
join types b on b.type = a.j->>'key'),
test3 (i, j) as
(select i, j::boolean as j from test2)
select i from test3 where j = true;

regards.

--
Kyotaro Horiguchi
NTT Open Source Software Center

In response to

Browse pgsql-bugs by date

  From Date Subject
Next Message Tom Lane 2020-10-28 03:27:05 Re: BUG #16688: psql removes only LF without CR at end of backquotes on windows.
Previous Message PG Bug reporting form 2020-10-28 01:58:57 BUG #16688: psql removes only LF without CR at end of backquotes on windows.