Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions regress/expected/list_comprehension.out
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,31 @@ SELECT * FROM cypher('list_comprehension', $$ CREATE n=()-[:edge]->() RETURN [n
[{"id": 281474976710664, "label": "", "properties": {}}::vertex, {"id": 281474976710665, "label": "", "properties": {}}::vertex]
(1 row)

-- Property access on the list-comprehension loop variable
SELECT * FROM cypher('list_comprehension', $$ RETURN [x IN [{name:'a'}, {name:'b'}] | x.name] $$) AS (result agtype);
result
------------
["a", "b"]
(1 row)

SELECT * FROM cypher('list_comprehension', $$ RETURN [x IN [{n:1}, {n:2}, {n:3}] WHERE x.n > 1 | x.n] $$) AS (result agtype);
result
--------
[2, 3]
(1 row)

SELECT * FROM cypher('list_comprehension', $$ MATCH p=()-[:edge]->() RETURN [n IN nodes(p) | n.name] $$) AS (result agtype);
result
--------------
[null, null]
(1 row)

SELECT * FROM cypher('list_comprehension', $$ MATCH (u:csm_match) WITH collect(u) AS ns RETURN [x IN ns | x.list] $$) AS (result agtype);
result
-------------------------
[["abc", "def", "ghi"]]
(1 row)

-- Multiple list comprehensions in RETURN and WITH clause
SELECT * FROM cypher('list_comprehension', $$ RETURN [u IN [1,2,3]], [u IN [1,2,3]] $$) AS (result agtype, result2 agtype);
result | result2
Expand Down
148 changes: 148 additions & 0 deletions regress/expected/predicate_functions.out
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,154 @@ $$) AS (result agtype);
"even"
(1 row)

--
-- Property access on the loop variable
--
-- any: true (2 > 1) / false (none > 5)
SELECT * FROM cypher('predicate_functions', $$
RETURN any(x IN [{n: 1}, {n: 2}] WHERE x.n > 1)
$$) AS (result agtype);
result
--------
true
(1 row)

SELECT * FROM cypher('predicate_functions', $$
RETURN any(x IN [{n: 1}, {n: 2}] WHERE x.n > 5)
$$) AS (result agtype);
result
--------
false
(1 row)

-- all: true (both > 0) / false (not all > 1)
SELECT * FROM cypher('predicate_functions', $$
RETURN all(x IN [{n: 1}, {n: 2}] WHERE x.n > 0)
$$) AS (result agtype);
result
--------
true
(1 row)

SELECT * FROM cypher('predicate_functions', $$
RETURN all(x IN [{n: 1}, {n: 2}] WHERE x.n > 1)
$$) AS (result agtype);
result
--------
false
(1 row)

-- none: true (neither > 2) / false (one matches)
SELECT * FROM cypher('predicate_functions', $$
RETURN none(x IN [{n: 1}, {n: 2}] WHERE x.n > 2)
$$) AS (result agtype);
result
--------
true
(1 row)

SELECT * FROM cypher('predicate_functions', $$
RETURN none(x IN [{n: 1}, {n: 2}] WHERE x.n = 1)
$$) AS (result agtype);
result
--------
false
(1 row)

-- single: true (exactly one) / false (both match)
SELECT * FROM cypher('predicate_functions', $$
RETURN single(x IN [{n: 1}, {n: 2}] WHERE x.n = 1)
$$) AS (result agtype);
result
--------
true
(1 row)

SELECT * FROM cypher('predicate_functions', $$
RETURN single(x IN [{n: 1}, {n: 2}] WHERE x.n > 0)
$$) AS (result agtype);
result
--------
false
(1 row)

-- Property access on vertex loop variables over a collected node list
-- any: true ('even' exists) / false (no 'missing')
SELECT * FROM cypher('predicate_functions', $$
MATCH (u) WITH collect(u) AS ns
RETURN any(x IN ns WHERE x.name = 'even')
$$) AS (result agtype);
result
--------
true
(1 row)

SELECT * FROM cypher('predicate_functions', $$
MATCH (u) WITH collect(u) AS ns
RETURN any(x IN ns WHERE x.name = 'missing')
$$) AS (result agtype);
result
--------
false
(1 row)

-- all: true (all have non-empty vals) / false (not all named 'even')
SELECT * FROM cypher('predicate_functions', $$
MATCH (u) WITH collect(u) AS ns
RETURN all(x IN ns WHERE size(x.vals) > 0)
$$) AS (result agtype);
result
--------
true
(1 row)

SELECT * FROM cypher('predicate_functions', $$
MATCH (u) WITH collect(u) AS ns
RETURN all(x IN ns WHERE x.name = 'even')
$$) AS (result agtype);
result
--------
false
(1 row)

-- none: true (none 'missing') / false ('even' matches)
SELECT * FROM cypher('predicate_functions', $$
MATCH (u) WITH collect(u) AS ns
RETURN none(x IN ns WHERE x.name = 'missing')
$$) AS (result agtype);
result
--------
true
(1 row)

SELECT * FROM cypher('predicate_functions', $$
MATCH (u) WITH collect(u) AS ns
RETURN none(x IN ns WHERE x.name = 'even')
$$) AS (result agtype);
result
--------
false
(1 row)

-- single: true (only one 'odd') / false (all have non-empty vals)
SELECT * FROM cypher('predicate_functions', $$
MATCH (u) WITH collect(u) AS ns
RETURN single(x IN ns WHERE x.name = 'odd')
$$) AS (result agtype);
result
--------
true
(1 row)

SELECT * FROM cypher('predicate_functions', $$
MATCH (u) WITH collect(u) AS ns
RETURN single(x IN ns WHERE size(x.vals) > 0)
$$) AS (result agtype);
result
--------
false
(1 row)

--
-- Predicate functions in boolean expressions
--
Expand Down
6 changes: 6 additions & 0 deletions regress/sql/list_comprehension.sql
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,12 @@ SELECT * FROM cypher('list_comprehension', $$ WITH 1 AS m RETURN [m IN [1, 2, 3]
SELECT * FROM cypher('list_comprehension', $$ WITH [m IN [1,2,3]] AS m RETURN [m IN [1, 2, 3]], m $$) AS (result agtype, result2 agtype);
SELECT * FROM cypher('list_comprehension', $$ CREATE n=()-[:edge]->() RETURN [n IN nodes(n)] $$) AS (u agtype);

-- Property access on the list-comprehension loop variable
SELECT * FROM cypher('list_comprehension', $$ RETURN [x IN [{name:'a'}, {name:'b'}] | x.name] $$) AS (result agtype);
SELECT * FROM cypher('list_comprehension', $$ RETURN [x IN [{n:1}, {n:2}, {n:3}] WHERE x.n > 1 | x.n] $$) AS (result agtype);
SELECT * FROM cypher('list_comprehension', $$ MATCH p=()-[:edge]->() RETURN [n IN nodes(p) | n.name] $$) AS (result agtype);
SELECT * FROM cypher('list_comprehension', $$ MATCH (u:csm_match) WITH collect(u) AS ns RETURN [x IN ns | x.list] $$) AS (result agtype);

-- Multiple list comprehensions in RETURN and WITH clause
SELECT * FROM cypher('list_comprehension', $$ RETURN [u IN [1,2,3]], [u IN [1,2,3]] $$) AS (result agtype, result2 agtype);
SELECT * FROM cypher('list_comprehension', $$ RETURN [u IN [1,2,3] WHERE u>1], [u IN [1,2,3] WHERE u>2] $$) AS (result agtype, result2 agtype);
Expand Down
84 changes: 84 additions & 0 deletions regress/sql/predicate_functions.sql
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,90 @@ SELECT * FROM cypher('predicate_functions', $$
ORDER BY u.name
$$) AS (result agtype);

--
-- Property access on the loop variable
--
-- any: true (2 > 1) / false (none > 5)
SELECT * FROM cypher('predicate_functions', $$
RETURN any(x IN [{n: 1}, {n: 2}] WHERE x.n > 1)
$$) AS (result agtype);

SELECT * FROM cypher('predicate_functions', $$
RETURN any(x IN [{n: 1}, {n: 2}] WHERE x.n > 5)
$$) AS (result agtype);

-- all: true (both > 0) / false (not all > 1)
SELECT * FROM cypher('predicate_functions', $$
RETURN all(x IN [{n: 1}, {n: 2}] WHERE x.n > 0)
$$) AS (result agtype);

SELECT * FROM cypher('predicate_functions', $$
RETURN all(x IN [{n: 1}, {n: 2}] WHERE x.n > 1)
$$) AS (result agtype);

-- none: true (neither > 2) / false (one matches)
SELECT * FROM cypher('predicate_functions', $$
RETURN none(x IN [{n: 1}, {n: 2}] WHERE x.n > 2)
$$) AS (result agtype);

SELECT * FROM cypher('predicate_functions', $$
RETURN none(x IN [{n: 1}, {n: 2}] WHERE x.n = 1)
$$) AS (result agtype);

-- single: true (exactly one) / false (both match)
SELECT * FROM cypher('predicate_functions', $$
RETURN single(x IN [{n: 1}, {n: 2}] WHERE x.n = 1)
$$) AS (result agtype);

SELECT * FROM cypher('predicate_functions', $$
RETURN single(x IN [{n: 1}, {n: 2}] WHERE x.n > 0)
$$) AS (result agtype);

-- Property access on vertex loop variables over a collected node list
-- any: true ('even' exists) / false (no 'missing')
SELECT * FROM cypher('predicate_functions', $$
MATCH (u) WITH collect(u) AS ns
RETURN any(x IN ns WHERE x.name = 'even')
$$) AS (result agtype);

SELECT * FROM cypher('predicate_functions', $$
MATCH (u) WITH collect(u) AS ns
RETURN any(x IN ns WHERE x.name = 'missing')
$$) AS (result agtype);

-- all: true (all have non-empty vals) / false (not all named 'even')
SELECT * FROM cypher('predicate_functions', $$
MATCH (u) WITH collect(u) AS ns
RETURN all(x IN ns WHERE size(x.vals) > 0)
$$) AS (result agtype);

SELECT * FROM cypher('predicate_functions', $$
MATCH (u) WITH collect(u) AS ns
RETURN all(x IN ns WHERE x.name = 'even')
$$) AS (result agtype);

-- none: true (none 'missing') / false ('even' matches)
SELECT * FROM cypher('predicate_functions', $$
MATCH (u) WITH collect(u) AS ns
RETURN none(x IN ns WHERE x.name = 'missing')
$$) AS (result agtype);

SELECT * FROM cypher('predicate_functions', $$
MATCH (u) WITH collect(u) AS ns
RETURN none(x IN ns WHERE x.name = 'even')
$$) AS (result agtype);

-- single: true (only one 'odd') / false (all have non-empty vals)
SELECT * FROM cypher('predicate_functions', $$
MATCH (u) WITH collect(u) AS ns
RETURN single(x IN ns WHERE x.name = 'odd')
$$) AS (result agtype);

SELECT * FROM cypher('predicate_functions', $$
MATCH (u) WITH collect(u) AS ns
RETURN single(x IN ns WHERE size(x.vals) > 0)
$$) AS (result agtype);

--
-- Predicate functions in boolean expressions
--
Expand Down
15 changes: 4 additions & 11 deletions src/backend/parser/cypher_expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -1326,21 +1326,14 @@ static Node *transform_column_ref_for_indirection(cypher_parsestate *cpstate,
}

/* find the properties column of the NSI and return a var for it */
node = scanNSItemForColumn(pstate, pnsi, levels_up, "properties",
node = scanNSItemForColumn(pstate, pnsi, levels_up, "properties",
cr->location);

/*
* Error out if we couldn't find it.
*
* TODO: Should we error out or return NULL for further processing?
* For now, just error out.
* If there's no "properties" column, continue transforming the
* ColumnRef as an agtype value and try to apply the indirection via
Comment thread
MuhammadTahaNaveed marked this conversation as resolved.
* agtype_access_operator.
*/
if (!node)
{
ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("could not find properties for %s", relname)));
}

return node;
}

Expand Down
Loading