GRAPH_TABLE pattern WHERE clause is not coerced to boolean

Started by Ewan Young21 days ago6 messageshackers
Beta feature

Hackorum builds and tests every patch posted to the lists, not only commitfest submissions. This is Hackorum's own CI rather than the PostgreSQL project's, and it is still under testing - please report anything that looks wrong.

won't retrysuccessCI history

This thread has been committed, so CI has stopped here. Anything below is the last result it produced.

You can run a PostgreSQL built from this patch straight from Docker, with no checkout and no build:

docker run --rm -p 5432:5432 ghcr.io/hackorum-dev/postgres-patch:t253617
psql -h localhost -U postgres

Built from patchset v1 (message #1), September 02, 2026 at 08:13 AM.

Every patchset is also pushed to a branch of our PostgreSQL fork, so you can check out the same tree CI built. Without a PostgreSQL checkout:

git clone --branch t253617_1 https://github.com/hackorum-dev/postgres.git

In a checkout you already have, add the fork once:

git remote add hackorum https://github.com/hackorum-dev/postgres.git

then, for this patchset and every later one:

git fetch hackorum t253617_1 && git checkout t253617_1

Patchset v1 (message #1) is on t253617_1

Jump to latest
#1Ewan Young
kdbase.hack@gmail.com

Hi

The WHERE clauses inside a GRAPH_TABLE pattern -- both the element-level
one (MATCH (c IS customers WHERE ...)) and the graph-pattern-level one
(MATCH ... WHERE ...) -- are transformed with a bare transformExpr()
and never go through coerce_to_boolean(). So a WHERE clause of any
type is accepted, and its raw datum is used as the qual:

create table customers (id int primary key, name text);
insert into customers values (1,'alice'),(2,null),(3,'carol');
create property graph g
vertex tables (customers key (id) label customer properties (id, name));

select * from graph_table (g match (c is customer where c.name)
columns (c.id));
id
----
1
3
(2 rows)

EXPLAIN shows "Filter: name". The never-null text pointer is always
taken as true, so the condition silently degenerates to roughly
"name IS NOT NULL": the NULL-name row disappears with no error.
Numeric quals are evaluated by bit pattern ("WHERE 1" is true,
"WHERE 0" is false), and even "WHERE row(1,2)" is accepted. The same
clause outside GRAPH_TABLE gives the usual

ERROR: argument of WHERE must be type boolean, not type text

The attached patch routes both sites through transformWhereClause(),
like every other WHERE clause, and adds regression tests for the
element-level and pattern-level cases. make check passes. The code is
the same in REL_19_STABLE, so v19 is affected as well.

--
Regards,
Ewan Young

Attachments:

t253617_1
v1-0001-Coerce-GRAPH_TABLE-pattern-WHERE-clauses-to-boolean.patchapplication/octet-stream; name=v1-0001-Coerce-GRAPH_TABLE-pattern-WHERE-clauses-to-boolean.patchDownload+11-3
#2Chao Li
li.evan.chao@gmail.com
In reply to: Ewan Young (#1)
Re: GRAPH_TABLE pattern WHERE clause is not coerced to boolean

On Aug 31, 2026, at 15:32, Ewan Young <kdbase.hack@gmail.com> wrote:

Hi

The WHERE clauses inside a GRAPH_TABLE pattern -- both the element-level
one (MATCH (c IS customers WHERE ...)) and the graph-pattern-level one
(MATCH ... WHERE ...) -- are transformed with a bare transformExpr()
and never go through coerce_to_boolean(). So a WHERE clause of any
type is accepted, and its raw datum is used as the qual:

create table customers (id int primary key, name text);
insert into customers values (1,'alice'),(2,null),(3,'carol');
create property graph g
vertex tables (customers key (id) label customer properties (id, name));

select * from graph_table (g match (c is customer where c.name)
columns (c.id));
id
----
1
3
(2 rows)

EXPLAIN shows "Filter: name". The never-null text pointer is always
taken as true, so the condition silently degenerates to roughly
"name IS NOT NULL": the NULL-name row disappears with no error.
Numeric quals are evaluated by bit pattern ("WHERE 1" is true,
"WHERE 0" is false), and even "WHERE row(1,2)" is accepted. The same
clause outside GRAPH_TABLE gives the usual

ERROR: argument of WHERE must be type boolean, not type text

The attached patch routes both sites through transformWhereClause(),
like every other WHERE clause, and adds regression tests for the
element-level and pattern-level cases. make check passes. The code is
the same in REL_19_STABLE, so v19 is affected as well.

--
Regards,
Ewan Young
<v1-0001-Coerce-GRAPH_TABLE-pattern-WHERE-clauses-to-boolean.patch>

The patch looks good to me. As this is a v19 bug, it might be worth noting in the Open Items list.

Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/

#3Ewan Young
kdbase.hack@gmail.com
In reply to: Chao Li (#2)
Re: GRAPH_TABLE pattern WHERE clause is not coerced to boolean

Thanks for the review!

On Mon, Aug 31, 2026 at 4:38 PM Chao Li <li.evan.chao@gmail.com> wrote:

On Aug 31, 2026, at 15:32, Ewan Young <kdbase.hack@gmail.com> wrote:

Hi

The WHERE clauses inside a GRAPH_TABLE pattern -- both the element-level
one (MATCH (c IS customers WHERE ...)) and the graph-pattern-level one
(MATCH ... WHERE ...) -- are transformed with a bare transformExpr()
and never go through coerce_to_boolean(). So a WHERE clause of any
type is accepted, and its raw datum is used as the qual:

create table customers (id int primary key, name text);
insert into customers values (1,'alice'),(2,null),(3,'carol');
create property graph g
vertex tables (customers key (id) label customer properties (id, name));

select * from graph_table (g match (c is customer where c.name)
columns (c.id));
id
----
1
3
(2 rows)

EXPLAIN shows "Filter: name". The never-null text pointer is always
taken as true, so the condition silently degenerates to roughly
"name IS NOT NULL": the NULL-name row disappears with no error.
Numeric quals are evaluated by bit pattern ("WHERE 1" is true,
"WHERE 0" is false), and even "WHERE row(1,2)" is accepted. The same
clause outside GRAPH_TABLE gives the usual

ERROR: argument of WHERE must be type boolean, not type text

The attached patch routes both sites through transformWhereClause(),
like every other WHERE clause, and adds regression tests for the
element-level and pattern-level cases. make check passes. The code is
the same in REL_19_STABLE, so v19 is affected as well.

--
Regards,
Ewan Young
<v1-0001-Coerce-GRAPH_TABLE-pattern-WHERE-clauses-to-boolean.patch>

The patch looks good to me. As this is a v19 bug, it might be worth noting in the Open Items list.

Agreed -- I don't have wiki edit access though; could someone add it
under "Open Issues"?

Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/

--
Regards,
Ewan Young

#4Chao Li
li.evan.chao@gmail.com
In reply to: Ewan Young (#3)
Re: GRAPH_TABLE pattern WHERE clause is not coerced to boolean

On Aug 31, 2026, at 18:08, Ewan Young <kdbase.hack@gmail.com> wrote:

Thanks for the review!

On Mon, Aug 31, 2026 at 4:38 PM Chao Li <li.evan.chao@gmail.com> wrote:

On Aug 31, 2026, at 15:32, Ewan Young <kdbase.hack@gmail.com> wrote:

Hi

The WHERE clauses inside a GRAPH_TABLE pattern -- both the element-level
one (MATCH (c IS customers WHERE ...)) and the graph-pattern-level one
(MATCH ... WHERE ...) -- are transformed with a bare transformExpr()
and never go through coerce_to_boolean(). So a WHERE clause of any
type is accepted, and its raw datum is used as the qual:

create table customers (id int primary key, name text);
insert into customers values (1,'alice'),(2,null),(3,'carol');
create property graph g
vertex tables (customers key (id) label customer properties (id, name));

select * from graph_table (g match (c is customer where c.name)
columns (c.id));
id
----
1
3
(2 rows)

EXPLAIN shows "Filter: name". The never-null text pointer is always
taken as true, so the condition silently degenerates to roughly
"name IS NOT NULL": the NULL-name row disappears with no error.
Numeric quals are evaluated by bit pattern ("WHERE 1" is true,
"WHERE 0" is false), and even "WHERE row(1,2)" is accepted. The same
clause outside GRAPH_TABLE gives the usual

ERROR: argument of WHERE must be type boolean, not type text

The attached patch routes both sites through transformWhereClause(),
like every other WHERE clause, and adds regression tests for the
element-level and pattern-level cases. make check passes. The code is
the same in REL_19_STABLE, so v19 is affected as well.

--
Regards,
Ewan Young
<v1-0001-Coerce-GRAPH_TABLE-pattern-WHERE-clauses-to-boolean.patch>

The patch looks good to me. As this is a v19 bug, it might be worth noting in the Open Items list.

Agreed -- I don't have wiki edit access though; could someone add it
under "Open Issues"?

I just helped add the item.

Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/

#5Ewan Young
kdbase.hack@gmail.com
In reply to: Chao Li (#4)
Re: GRAPH_TABLE pattern WHERE clause is not coerced to boolean

Thanks for adding it!

On Mon, Aug 31, 2026 at 7:27 PM Chao Li <li.evan.chao@gmail.com> wrote:

On Aug 31, 2026, at 18:08, Ewan Young <kdbase.hack@gmail.com> wrote:

Thanks for the review!

On Mon, Aug 31, 2026 at 4:38 PM Chao Li <li.evan.chao@gmail.com> wrote:

On Aug 31, 2026, at 15:32, Ewan Young <kdbase.hack@gmail.com> wrote:

Hi

The WHERE clauses inside a GRAPH_TABLE pattern -- both the element-level
one (MATCH (c IS customers WHERE ...)) and the graph-pattern-level one
(MATCH ... WHERE ...) -- are transformed with a bare transformExpr()
and never go through coerce_to_boolean(). So a WHERE clause of any
type is accepted, and its raw datum is used as the qual:

create table customers (id int primary key, name text);
insert into customers values (1,'alice'),(2,null),(3,'carol');
create property graph g
vertex tables (customers key (id) label customer properties (id, name));

select * from graph_table (g match (c is customer where c.name)
columns (c.id));
id
----
1
3
(2 rows)

EXPLAIN shows "Filter: name". The never-null text pointer is always
taken as true, so the condition silently degenerates to roughly
"name IS NOT NULL": the NULL-name row disappears with no error.
Numeric quals are evaluated by bit pattern ("WHERE 1" is true,
"WHERE 0" is false), and even "WHERE row(1,2)" is accepted. The same
clause outside GRAPH_TABLE gives the usual

ERROR: argument of WHERE must be type boolean, not type text

The attached patch routes both sites through transformWhereClause(),
like every other WHERE clause, and adds regression tests for the
element-level and pattern-level cases. make check passes. The code is
the same in REL_19_STABLE, so v19 is affected as well.

--
Regards,
Ewan Young
<v1-0001-Coerce-GRAPH_TABLE-pattern-WHERE-clauses-to-boolean.patch>

The patch looks good to me. As this is a v19 bug, it might be worth noting in the Open Items list.

Agreed -- I don't have wiki edit access though; could someone add it
under "Open Issues"?

I just helped add the item.

Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/

--
Regards,
Ewan Young

#6Peter Eisentraut
peter_e@gmx.net
In reply to: Ewan Young (#1)
Re: GRAPH_TABLE pattern WHERE clause is not coerced to boolean

On 31.08.26 09:32, Ewan Young wrote:

Hi

The WHERE clauses inside a GRAPH_TABLE pattern -- both the element-level
one (MATCH (c IS customers WHERE ...)) and the graph-pattern-level one
(MATCH ... WHERE ...) -- are transformed with a bare transformExpr()
and never go through coerce_to_boolean(). So a WHERE clause of any
type is accepted, and its raw datum is used as the qual:

create table customers (id int primary key, name text);
insert into customers values (1,'alice'),(2,null),(3,'carol');
create property graph g
vertex tables (customers key (id) label customer properties (id, name));

select * from graph_table (g match (c is customer where c.name)
columns (c.id));
id
----
1
3
(2 rows)

EXPLAIN shows "Filter: name". The never-null text pointer is always
taken as true, so the condition silently degenerates to roughly
"name IS NOT NULL": the NULL-name row disappears with no error.
Numeric quals are evaluated by bit pattern ("WHERE 1" is true,
"WHERE 0" is false), and even "WHERE row(1,2)" is accepted. The same
clause outside GRAPH_TABLE gives the usual

ERROR: argument of WHERE must be type boolean, not type text

The attached patch routes both sites through transformWhereClause(),
like every other WHERE clause, and adds regression tests for the
element-level and pattern-level cases. make check passes. The code is
the same in REL_19_STABLE, so v19 is affected as well.

Fixed, thanks.