mirror of
https://github.com/postgres/postgres.git
synced 2026-07-09 17:51:00 -04:00
Fix replace_property_refs() ignoring the root of expression tree
replace_property_refs() called expression_tree_mutator() with the root of the expression tree as the input node. But expression_tree_mutator() does not call the mutator function on the root node, so the root node remains unchanged. If the root node is a property reference or a lateral reference -- the two node kinds that replace_property_refs_mutator() rewrites -- it is returned unchanged. Modules after the rewriter do not know about property reference nodes, resulting in "ERROR: unrecognized node type: 63". Since varlevelsup of lateral references is not incremented, they are not resolved correctly in the planner, leading to many different symptoms. Fix this by calling replace_property_refs_mutator() directly from replace_property_refs(), similar to how other mutator functions do. The only case when a property reference or a lateral reference can be the root of a GRAPH_TABLE expression tree is when it is a bare property reference or a bare lateral reference in the WHERE clause. The COLUMNS clause is passed to replace_property_refs() as a targetlist. Every other expression has at least one expression node covering the property reference or a lateral reference in the expression tree. That explains why this bug was not seen so far. Author: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> Reported-by: Noah Misch <noah@leadboat.com> Discussion: https://www.postgresql.org/message-id/flat/20260630173053.51.noahmisch%40microsoft.com
This commit is contained in:
parent
4b587f666a
commit
16a4b3ef8e
3 changed files with 41 additions and 16 deletions
|
|
@ -1159,7 +1159,7 @@ replace_property_refs(Oid propgraphid, Node *node, const List *mappings)
|
|||
context.mappings = mappings;
|
||||
context.propgraphid = propgraphid;
|
||||
|
||||
return expression_tree_mutator(node, replace_property_refs_mutator, &context);
|
||||
return replace_property_refs_mutator(node, &context);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -248,12 +248,12 @@ SELECT * FROM GRAPH_TABLE (myshop MATCH (c IS customers)->(o IS orders) COLUMNS
|
|||
-- Use table with a column name same as a property in the property graph so as
|
||||
-- to test resolution preferences. Property references are preferred over
|
||||
-- lateral table references.
|
||||
CREATE TABLE x1 (a int, address text);
|
||||
INSERT INTO x1 VALUES (1, 'one'), (2, 'two');
|
||||
CREATE TABLE x1 (a int, address text, flag boolean);
|
||||
INSERT INTO x1 VALUES (1, 'one', true), (2, 'two', false);
|
||||
SELECT * FROM x1, GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.address = 'US' AND c.customer_id = x1.a)-[IS customer_orders]->(o IS orders) COLUMNS (c.name AS customer_name, c.customer_id AS cid));
|
||||
a | address | customer_name | cid
|
||||
---+---------+---------------+-----
|
||||
1 | one | customer1 | 1
|
||||
a | address | flag | customer_name | cid
|
||||
---+---------+------+---------------+-----
|
||||
1 | one | t | customer1 | 1
|
||||
(1 row)
|
||||
|
||||
SELECT x1.a, g.* FROM x1, GRAPH_TABLE (myshop MATCH (x1 IS customers WHERE x1.address = 'US')-[IS customer_orders]->(o IS orders) COLUMNS (x1.name AS customer_name, x1.customer_id AS cid, o.order_id)) g;
|
||||
|
|
@ -263,6 +263,13 @@ SELECT x1.a, g.* FROM x1, GRAPH_TABLE (myshop MATCH (x1 IS customers WHERE x1.ad
|
|||
2 | customer1 | 1 | 1
|
||||
(2 rows)
|
||||
|
||||
-- bare lateral reference in WHERE clause
|
||||
SELECT * FROM x1, GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.customer_id = x1.a) WHERE x1.flag COLUMNS (c.name AS customer_name));
|
||||
a | address | flag | customer_name
|
||||
---+---------+------+---------------
|
||||
1 | one | t | customer1
|
||||
(1 row)
|
||||
|
||||
-- lateral reference with multi-label pattern, which is rewritten as UNION of
|
||||
-- path queries
|
||||
SELECT x1.a, g.* FROM x1,
|
||||
|
|
@ -864,12 +871,12 @@ CREATE TABLE cv2 () INHERITS (pv);
|
|||
INSERT INTO pv VALUES (1, 10);
|
||||
INSERT INTO cv1 VALUES (2, 20);
|
||||
INSERT INTO cv2 VALUES (3, 30);
|
||||
CREATE TABLE pe (id int, src int, dest int, val int);
|
||||
CREATE TABLE pe (id int, src int, dest int, val int, flag boolean);
|
||||
CREATE TABLE ce1 () INHERITS (pe);
|
||||
CREATE TABLE ce2 () INHERITS (pe);
|
||||
INSERT INTO pe VALUES (1, 1, 2, 100);
|
||||
INSERT INTO ce1 VALUES (2, 2, 3, 200);
|
||||
INSERT INTO ce2 VALUES (3, 3, 1, 300);
|
||||
INSERT INTO pe VALUES (1, 1, 2, 100, false);
|
||||
INSERT INTO ce1 VALUES (2, 2, 3, 200, false);
|
||||
INSERT INTO ce2 VALUES (3, 3, 1, 300, true);
|
||||
CREATE PROPERTY GRAPH g3
|
||||
NODE TABLES (
|
||||
pv KEY (id)
|
||||
|
|
@ -887,6 +894,19 @@ SELECT * FROM GRAPH_TABLE (g3 MATCH (s IS pv)-[e IS pe]->(d IS pv) COLUMNS (s.va
|
|||
30 | 300 | 10
|
||||
(3 rows)
|
||||
|
||||
-- bare property reference in WHERE clause
|
||||
SELECT * FROM GRAPH_TABLE (g3 MATCH (s IS pv)-[e IS pe WHERE e.flag]->(d IS pv) COLUMNS (s.val, e.val, d.val)) ORDER BY 1, 2, 3;
|
||||
val | val | val
|
||||
-----+-----+-----
|
||||
30 | 300 | 10
|
||||
(1 row)
|
||||
|
||||
SELECT * FROM GRAPH_TABLE (g3 MATCH (s IS pv)-[e IS pe]->(d IS pv) WHERE e.flag COLUMNS (s.val, e.val, d.val)) ORDER BY 1, 2, 3;
|
||||
val | val | val
|
||||
-----+-----+-----
|
||||
30 | 300 | 10
|
||||
(1 row)
|
||||
|
||||
-- temporary property graph
|
||||
CREATE TEMPORARY PROPERTY GRAPH gtmp
|
||||
VERTEX TABLES (
|
||||
|
|
|
|||
|
|
@ -156,10 +156,12 @@ SELECT * FROM GRAPH_TABLE (myshop MATCH (c IS customers)->(o IS orders) COLUMNS
|
|||
-- Use table with a column name same as a property in the property graph so as
|
||||
-- to test resolution preferences. Property references are preferred over
|
||||
-- lateral table references.
|
||||
CREATE TABLE x1 (a int, address text);
|
||||
INSERT INTO x1 VALUES (1, 'one'), (2, 'two');
|
||||
CREATE TABLE x1 (a int, address text, flag boolean);
|
||||
INSERT INTO x1 VALUES (1, 'one', true), (2, 'two', false);
|
||||
SELECT * FROM x1, GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.address = 'US' AND c.customer_id = x1.a)-[IS customer_orders]->(o IS orders) COLUMNS (c.name AS customer_name, c.customer_id AS cid));
|
||||
SELECT x1.a, g.* FROM x1, GRAPH_TABLE (myshop MATCH (x1 IS customers WHERE x1.address = 'US')-[IS customer_orders]->(o IS orders) COLUMNS (x1.name AS customer_name, x1.customer_id AS cid, o.order_id)) g;
|
||||
-- bare lateral reference in WHERE clause
|
||||
SELECT * FROM x1, GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.customer_id = x1.a) WHERE x1.flag COLUMNS (c.name AS customer_name));
|
||||
-- lateral reference with multi-label pattern, which is rewritten as UNION of
|
||||
-- path queries
|
||||
SELECT x1.a, g.* FROM x1,
|
||||
|
|
@ -483,12 +485,12 @@ CREATE TABLE cv2 () INHERITS (pv);
|
|||
INSERT INTO pv VALUES (1, 10);
|
||||
INSERT INTO cv1 VALUES (2, 20);
|
||||
INSERT INTO cv2 VALUES (3, 30);
|
||||
CREATE TABLE pe (id int, src int, dest int, val int);
|
||||
CREATE TABLE pe (id int, src int, dest int, val int, flag boolean);
|
||||
CREATE TABLE ce1 () INHERITS (pe);
|
||||
CREATE TABLE ce2 () INHERITS (pe);
|
||||
INSERT INTO pe VALUES (1, 1, 2, 100);
|
||||
INSERT INTO ce1 VALUES (2, 2, 3, 200);
|
||||
INSERT INTO ce2 VALUES (3, 3, 1, 300);
|
||||
INSERT INTO pe VALUES (1, 1, 2, 100, false);
|
||||
INSERT INTO ce1 VALUES (2, 2, 3, 200, false);
|
||||
INSERT INTO ce2 VALUES (3, 3, 1, 300, true);
|
||||
CREATE PROPERTY GRAPH g3
|
||||
NODE TABLES (
|
||||
pv KEY (id)
|
||||
|
|
@ -499,6 +501,9 @@ CREATE PROPERTY GRAPH g3
|
|||
DESTINATION KEY(dest) REFERENCES pv(id)
|
||||
);
|
||||
SELECT * FROM GRAPH_TABLE (g3 MATCH (s IS pv)-[e IS pe]->(d IS pv) COLUMNS (s.val, e.val, d.val)) ORDER BY 1, 2, 3;
|
||||
-- bare property reference in WHERE clause
|
||||
SELECT * FROM GRAPH_TABLE (g3 MATCH (s IS pv)-[e IS pe WHERE e.flag]->(d IS pv) COLUMNS (s.val, e.val, d.val)) ORDER BY 1, 2, 3;
|
||||
SELECT * FROM GRAPH_TABLE (g3 MATCH (s IS pv)-[e IS pe]->(d IS pv) WHERE e.flag COLUMNS (s.val, e.val, d.val)) ORDER BY 1, 2, 3;
|
||||
-- temporary property graph
|
||||
CREATE TEMPORARY PROPERTY GRAPH gtmp
|
||||
VERTEX TABLES (
|
||||
|
|
|
|||
Loading…
Reference in a new issue