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
13 changes: 12 additions & 1 deletion age--1.5.0--y.y.y.sql
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,15 @@ PARALLEL SAFE
AS 'MODULE_PATHNAME';

CREATE CAST (agtype AS json)
WITH FUNCTION ag_catalog.agtype_to_json(agtype);
WITH FUNCTION ag_catalog.agtype_to_json(agtype);

CREATE FUNCTION ag_catalog.agtype_array_to_agtype(agtype[])
RETURNS agtype
LANGUAGE c
IMMUTABLE
RETURNS NULL ON NULL INPUT
PARALLEL SAFE
AS 'MODULE_PATHNAME';

CREATE CAST (agtype[] AS agtype)
WITH FUNCTION ag_catalog.agtype_array_to_agtype(agtype[]);
102 changes: 79 additions & 23 deletions regress/expected/list_comprehension.out
Original file line number Diff line number Diff line change
Expand Up @@ -166,45 +166,50 @@ SELECT * FROM cypher('list_comprehension', $$ MATCH p=(u) RETURN [i IN range(0,
SELECT * FROM cypher('list_comprehension', $$ MATCH (u) RETURN [i IN u.list] $$) AS (result agtype);
result
-------------------------
[0, 2, 4, 6, 8, 10, 12]
[1, 3, 5, 7, 9, 11, 13]
[]
[0, 2, 4, 6, 8, 10, 12]
(3 rows)

SELECT * FROM cypher('list_comprehension', $$ MATCH (u) RETURN [i IN u.list WHERE i % 3 = 0] $$) AS (result agtype);
result
------------
[0, 6, 12]
[3, 9]
(2 rows)
[]
(3 rows)

SELECT * FROM cypher('list_comprehension', $$ MATCH (u) RETURN [i IN u.list WHERE i % 3 = 0 | i/3] $$) AS (result agtype);
result
-----------
[0, 2, 4]
[1, 3]
(2 rows)
[]
(3 rows)

SELECT * FROM cypher('list_comprehension', $$ MATCH (u) RETURN [i IN u.list WHERE i % 3 = 0 | i/3][1] $$) AS (result agtype);
result
--------
2
3
(2 rows)

(3 rows)

SELECT * FROM cypher('list_comprehension', $$ MATCH (u) RETURN [i IN u.list WHERE i % 3 = 0 | i/3][0..2] $$) AS (result agtype);
result
--------
[0, 2]
[1, 3]
(2 rows)
[]
(3 rows)

SELECT * FROM cypher('list_comprehension', $$ MATCH (u) RETURN [i IN u.list WHERE i % 3 = 0 | i/3][0..2][1] $$) AS (result agtype);
result
--------
2
3
(2 rows)

(3 rows)

-- Nested cases
SELECT * FROM cypher('list_comprehension', $$ RETURN [i IN [i IN [1,2,3]]] $$) AS (result agtype);
Expand Down Expand Up @@ -299,9 +304,9 @@ SELECT * FROM cypher('list_comprehension', $$ MATCH (u) WHERE u.list@>[i IN rang
SELECT * FROM cypher('list_comprehension', $$ MATCH (u) MATCH (v) WHERE v.list=[i IN u.list] RETURN v $$) AS (result agtype);
result
-----------------------------------------------------------------------------------------------
{"id": 281474976710659, "label": "", "properties": {"list": []}}::vertex
{"id": 281474976710657, "label": "", "properties": {"list": [0, 2, 4, 6, 8, 10, 12]}}::vertex
{"id": 281474976710658, "label": "", "properties": {"list": [1, 3, 5, 7, 9, 11, 13]}}::vertex
{"id": 281474976710659, "label": "", "properties": {"list": []}}::vertex
(3 rows)

SELECT * FROM cypher('list_comprehension', $$ MATCH (u {list:[i IN range(0,12,2)]}) RETURN u $$) AS (result agtype);
Expand Down Expand Up @@ -330,11 +335,11 @@ SELECT * FROM cypher('list_comprehension', $$ MATCH (u {list:[i IN range(1,13,2)
SELECT * FROM cypher('list_comprehension', $$ MATCH (u) MATCH (v {list:[i IN u.list]}) RETURN v $$) AS (result agtype);
result
-----------------------------------------------------------------------------------------------
{"id": 281474976710658, "label": "", "properties": {"list": [1, 3, 5, 7, 9, 11, 13]}}::vertex
{"id": 281474976710657, "label": "", "properties": {"list": [0, 2, 4, 6, 8, 10, 12]}}::vertex
{"id": 281474976710659, "label": "", "properties": {"list": []}}::vertex
{"id": 281474976710658, "label": "", "properties": {"list": [1, 3, 5, 7, 9, 11, 13]}}::vertex
{"id": 281474976710657, "label": "", "properties": {"list": [0, 2, 4, 6, 8, 10, 12]}}::vertex
{"id": 281474976710658, "label": "", "properties": {"list": [1, 3, 5, 7, 9, 11, 13]}}::vertex
{"id": 281474976710659, "label": "", "properties": {"list": []}}::vertex
(5 rows)

SELECT * FROM cypher('list_comprehension', $$ CREATE (u {list:[i IN range(12,24,2)]}) RETURN u $$) AS (result agtype);
Expand Down Expand Up @@ -371,26 +376,26 @@ SELECT * FROM cypher('list_comprehension', $$ MATCH(u) WITH u WHERE u.list = [u
SELECT * FROM cypher('list_comprehension', $$ MATCH(u) WITH u WHERE u.list = [u IN [0, 2, 4, 6, 8, 10, 12]] OR size(u.list) = 0 RETURN u $$) AS (u agtype);
u
-----------------------------------------------------------------------------------------------
{"id": 281474976710659, "label": "", "properties": {"list": []}}::vertex
{"id": 281474976710657, "label": "", "properties": {"list": [0, 2, 4, 6, 8, 10, 12]}}::vertex
{"id": 281474976710659, "label": "", "properties": {"list": []}}::vertex
(2 rows)

SELECT * FROM cypher('list_comprehension', $$ MATCH(u) WITH u WHERE u.list = [u IN [0, 2, 4, 6, 8, 10, 12]] OR size(u.list)::bool RETURN u $$) AS (u agtype);
u
--------------------------------------------------------------------------------------------------------
{"id": 281474976710657, "label": "", "properties": {"list": [0, 2, 4, 6, 8, 10, 12]}}::vertex
{"id": 281474976710658, "label": "", "properties": {"list": [1, 3, 5, 7, 9, 11, 13]}}::vertex
{"id": 281474976710661, "label": "", "properties": {"list": [6, 8, 10, 12]}}::vertex
{"id": 281474976710660, "label": "", "properties": {"list": [12, 14, 16, 18, 20, 22, 24]}}::vertex
{"id": 281474976710661, "label": "", "properties": {"list": [6, 8, 10, 12]}}::vertex
{"id": 281474976710662, "label": "", "properties": {"list": [25.0, 49.0, 81.0, 121.0, 169.0]}}::vertex
{"id": 281474976710657, "label": "", "properties": {"list": [0, 2, 4, 6, 8, 10, 12]}}::vertex
{"id": 281474976710663, "label": "", "properties": {"list": [1, 2, 3]}}::vertex
(6 rows)

SELECT * FROM cypher('list_comprehension', $$ MATCH(u) WITH u WHERE u.list = [u IN [0, 2, 4, 6, 8, 10, 12]] OR NOT size(u.list)::bool RETURN u $$) AS (u agtype);
u
-----------------------------------------------------------------------------------------------
{"id": 281474976710659, "label": "", "properties": {"list": []}}::vertex
{"id": 281474976710657, "label": "", "properties": {"list": [0, 2, 4, 6, 8, 10, 12]}}::vertex
{"id": 281474976710659, "label": "", "properties": {"list": []}}::vertex
(2 rows)

SELECT * FROM cypher('list_comprehension', $$ CREATE(u:csm_match {list: ['abc', 'def', 'ghi']}) $$) AS (u agtype);
Expand Down Expand Up @@ -473,9 +478,6 @@ SELECT * FROM cypher('list_comprehension', $$ MATCH(u {list: [0, 2, 4, 6, 8, 10,
ERROR: Invalid use of aggregation in this context
LINE 1: ..., $$ MATCH(u {list: [0, 2, 4, 6, 8, 10, 12]}) SET u.c = coll...
^
-- Known issue
SELECT * FROM cypher('list_comprehension', $$ MERGE (u {list:[i IN [1,2,3]]}) RETURN u $$) AS (result agtype);
ERROR: Aggref found in non-Agg plan node
-- List comprehension variable scoping
SELECT * FROM cypher('list_comprehension', $$ WITH 1 AS m, [m IN [1, 2, 3]] AS n RETURN [m IN [1, 2, 3]] $$) AS (result agtype);
result
Expand Down Expand Up @@ -622,24 +624,25 @@ SELECT * FROM cypher('list_comprehension', $$ MATCH (u) WHERE u.list=[i IN u.lis
result
---------------------------------------------------------------------------------------------------------------------------------------------------------------
{"id": 281474976710658, "label": "", "properties": {"list": [1, 3, 5, 7, 9, 11, 13]}}::vertex
{"id": 281474976710659, "label": "", "properties": {"list": []}}::vertex
{"id": 281474976710660, "label": "", "properties": {"list": [12, 14, 16, 18, 20, 22, 24]}}::vertex
{"id": 281474976710661, "label": "", "properties": {"list": [6, 8, 10, 12]}}::vertex
{"id": 281474976710662, "label": "", "properties": {"list": [25.0, 49.0, 81.0, 121.0, 169.0]}}::vertex
{"id": 281474976710657, "label": "", "properties": {"a": [], "b": [0, 1, 2, 3, 4, 5], "c": [0, 2, 4, 6, 8, 10, 12], "list": [0, 2, 4, 6, 8, 10, 12]}}::vertex
{"id": 281474976710663, "label": "", "properties": {"list": [1, 2, 3]}}::vertex
{"id": 281474976710659, "label": "", "properties": {"list": []}}::vertex
{"id": 281474976710661, "label": "", "properties": {"list": [6, 8, 10, 12]}}::vertex
{"id": 281474976710657, "label": "", "properties": {"a": [], "b": [0, 1, 2, 3, 4, 5], "c": [0, 2, 4, 6, 8, 10, 12], "list": [0, 2, 4, 6, 8, 10, 12]}}::vertex
{"id": 844424930131969, "label": "csm_match", "properties": {"list": ["abc", "def", "ghi"]}}::vertex
(8 rows)

SELECT * FROM cypher('list_comprehension', $$ MATCH (u) WHERE u.list=[i IN u.list WHERE i>0] RETURN u $$) AS (result agtype);
result
--------------------------------------------------------------------------------------------------------
{"id": 281474976710658, "label": "", "properties": {"list": [1, 3, 5, 7, 9, 11, 13]}}::vertex
{"id": 281474976710659, "label": "", "properties": {"list": []}}::vertex
{"id": 281474976710660, "label": "", "properties": {"list": [12, 14, 16, 18, 20, 22, 24]}}::vertex
{"id": 281474976710661, "label": "", "properties": {"list": [6, 8, 10, 12]}}::vertex
{"id": 281474976710662, "label": "", "properties": {"list": [25.0, 49.0, 81.0, 121.0, 169.0]}}::vertex
{"id": 281474976710663, "label": "", "properties": {"list": [1, 2, 3]}}::vertex
{"id": 281474976710661, "label": "", "properties": {"list": [6, 8, 10, 12]}}::vertex
(5 rows)
(6 rows)

SELECT * FROM cypher('list_comprehension', $$ MATCH (u) WHERE size([e in u.list where e starts with "a"])>0 RETURN u $$) AS (result agtype);
result
Expand All @@ -657,11 +660,64 @@ SELECT * FROM cypher('list_comprehension', $$ MATCH (u ={list:[i IN u.list WHERE
result
--------------------------------------------------------------------------------------------------------
{"id": 281474976710658, "label": "", "properties": {"list": [1, 3, 5, 7, 9, 11, 13]}}::vertex
{"id": 281474976710659, "label": "", "properties": {"list": []}}::vertex
{"id": 281474976710660, "label": "", "properties": {"list": [12, 14, 16, 18, 20, 22, 24]}}::vertex
{"id": 281474976710661, "label": "", "properties": {"list": [6, 8, 10, 12]}}::vertex
{"id": 281474976710662, "label": "", "properties": {"list": [25.0, 49.0, 81.0, 121.0, 169.0]}}::vertex
{"id": 281474976710663, "label": "", "properties": {"list": [1, 2, 3]}}::vertex
{"id": 281474976710661, "label": "", "properties": {"list": [6, 8, 10, 12]}}::vertex
(5 rows)
(6 rows)

-- List comprehension in MERGE
SELECT * FROM cypher('list_comprehension', $$ MERGE (u {list:[i IN [1,2,3]]}) RETURN u $$) AS (result agtype);
result
---------------------------------------------------------------------------------
{"id": 281474976710663, "label": "", "properties": {"list": [1, 2, 3]}}::vertex
(1 row)

SELECT * FROM cypher('list_comprehension', $$ MERGE (u ={list:[i IN [1,2,3] WHERE i>1]}) RETURN u $$) AS (result agtype);
result
------------------------------------------------------------------------------
{"id": 281474976710666, "label": "", "properties": {"list": [2, 3]}}::vertex
(1 row)

SELECT * FROM cypher('list_comprehension', $$ MERGE (u ={list:[i IN [1,2,3] WHERE i>1 | i^2]}) RETURN u $$) AS (result agtype);
result
----------------------------------------------------------------------------------
{"id": 281474976710667, "label": "", "properties": {"list": [4.0, 9.0]}}::vertex
(1 row)

-- Issue 1850
SELECT * FROM cypher('list_comprehension', $$ CREATE (u {list: [0, 2, 4, 6, 8, 10, 12]}) $$) AS (result agtype);
result
--------
(0 rows)

SELECT * FROM cypher('list_comprehension', $$ WITH [1, 2, 3] AS u UNWIND collect(u) AS v RETURN v $$) AS (result agtype);
ERROR: Invalid use of aggregation in this context
LINE 1: ...ist_comprehension', $$ WITH [1, 2, 3] AS u UNWIND collect(u)...
^
SELECT * FROM cypher('list_comprehension', $$ MATCH (u {list: [0, 2, 4, 6, 8, 10, 12]}) WITH u, collect(u.list) AS v SET u += {b: [u IN range(0, 5)]} SET u.c = [u IN v[0]] RETURN u $$) AS (result agtype);
result
---------------------------------------------------------------------------------------------------------------------------------------------------------------
{"id": 281474976710657, "label": "", "properties": {"a": [], "b": [0, 1, 2, 3, 4, 5], "c": [0, 2, 4, 6, 8, 10, 12], "list": [0, 2, 4, 6, 8, 10, 12]}}::vertex
{"id": 281474976710668, "label": "", "properties": {"b": [0, 1, 2, 3, 4, 5], "c": [0, 2, 4, 6, 8, 10, 12], "list": [0, 2, 4, 6, 8, 10, 12]}}::vertex
(2 rows)

SELECT * FROM cypher('list_comprehension', $$ MATCH (u {list: [0, 2, 4, 6, 8, 10, 12]}) SET u.c = collect(u.list) RETURN u $$) AS (u agtype);
ERROR: Invalid use of aggregation in this context
LINE 1: ... $$ MATCH (u {list: [0, 2, 4, 6, 8, 10, 12]}) SET u.c = coll...
^
SELECT * FROM cypher('list_comprehension', $$ MATCH (u {list: [0, 2, 4, 6, 8, 10, 12]}) WHERE u.list = [u IN [1, u]] RETURN u $$) AS (u agtype);
u
---
(0 rows)

SELECT * FROM cypher('list_comprehension', $$ MATCH (u {list: [0, 2, 4, 6, 8, 10, 12]}) WHERE u.list IN [u IN [1, u.list]] RETURN u $$) AS (u agtype);
u
---------------------------------------------------------------------------------------------------------------------------------------------------------------
{"id": 281474976710657, "label": "", "properties": {"a": [], "b": [0, 1, 2, 3, 4, 5], "c": [0, 2, 4, 6, 8, 10, 12], "list": [0, 2, 4, 6, 8, 10, 12]}}::vertex
{"id": 281474976710668, "label": "", "properties": {"b": [0, 1, 2, 3, 4, 5], "c": [0, 2, 4, 6, 8, 10, 12], "list": [0, 2, 4, 6, 8, 10, 12]}}::vertex
(2 rows)

-- Clean up
SELECT * FROM drop_graph('list_comprehension', true);
Expand Down
16 changes: 13 additions & 3 deletions regress/sql/list_comprehension.sql
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,6 @@ SELECT * FROM cypher('list_comprehension', $$ MATCH(u {list: [0, 2, 4, 6, 8, 10,
-- invalid use of aggregation in SET
SELECT * FROM cypher('list_comprehension', $$ MATCH(u {list: [0, 2, 4, 6, 8, 10, 12]}) SET u.c = collect(u.list) RETURN u $$) AS (u agtype);

-- Known issue
SELECT * FROM cypher('list_comprehension', $$ MERGE (u {list:[i IN [1,2,3]]}) RETURN u $$) AS (result agtype);

-- List comprehension variable scoping
SELECT * FROM cypher('list_comprehension', $$ WITH 1 AS m, [m IN [1, 2, 3]] AS n RETURN [m IN [1, 2, 3]] $$) AS (result agtype);
SELECT * FROM cypher('list_comprehension', $$ WITH 1 AS m RETURN [m IN [1, 2, 3]], m $$) AS (result agtype, result2 agtype);
Expand Down Expand Up @@ -164,5 +161,18 @@ SELECT * FROM cypher('list_comprehension', $$ MATCH (u) WHERE size([e in u.list
SELECT * FROM cypher('list_comprehension', $$ MATCH (u ={list:[i IN u.list | i+1]}) RETURN u $$) AS (result agtype);
SELECT * FROM cypher('list_comprehension', $$ MATCH (u ={list:[i IN u.list WHERE i>0]}) RETURN u$$) AS (result agtype);

-- List comprehension in MERGE
SELECT * FROM cypher('list_comprehension', $$ MERGE (u {list:[i IN [1,2,3]]}) RETURN u $$) AS (result agtype);
SELECT * FROM cypher('list_comprehension', $$ MERGE (u ={list:[i IN [1,2,3] WHERE i>1]}) RETURN u $$) AS (result agtype);
SELECT * FROM cypher('list_comprehension', $$ MERGE (u ={list:[i IN [1,2,3] WHERE i>1 | i^2]}) RETURN u $$) AS (result agtype);

-- Issue 1850
SELECT * FROM cypher('list_comprehension', $$ CREATE (u {list: [0, 2, 4, 6, 8, 10, 12]}) $$) AS (result agtype);
SELECT * FROM cypher('list_comprehension', $$ WITH [1, 2, 3] AS u UNWIND collect(u) AS v RETURN v $$) AS (result agtype);
SELECT * FROM cypher('list_comprehension', $$ MATCH (u {list: [0, 2, 4, 6, 8, 10, 12]}) WITH u, collect(u.list) AS v SET u += {b: [u IN range(0, 5)]} SET u.c = [u IN v[0]] RETURN u $$) AS (result agtype);
SELECT * FROM cypher('list_comprehension', $$ MATCH (u {list: [0, 2, 4, 6, 8, 10, 12]}) SET u.c = collect(u.list) RETURN u $$) AS (u agtype);
SELECT * FROM cypher('list_comprehension', $$ MATCH (u {list: [0, 2, 4, 6, 8, 10, 12]}) WHERE u.list = [u IN [1, u]] RETURN u $$) AS (u agtype);
SELECT * FROM cypher('list_comprehension', $$ MATCH (u {list: [0, 2, 4, 6, 8, 10, 12]}) WHERE u.list IN [u IN [1, u.list]] RETURN u $$) AS (u agtype);

-- Clean up
SELECT * FROM drop_graph('list_comprehension', true);
11 changes: 11 additions & 0 deletions sql/agtype_coercions.sql
Original file line number Diff line number Diff line change
Expand Up @@ -173,3 +173,14 @@ AS 'MODULE_PATHNAME';

CREATE CAST (agtype AS json)
WITH FUNCTION ag_catalog.agtype_to_json(agtype);

CREATE FUNCTION ag_catalog.agtype_array_to_agtype(agtype[])
RETURNS agtype
LANGUAGE c
IMMUTABLE
RETURNS NULL ON NULL INPUT
PARALLEL SAFE
AS 'MODULE_PATHNAME';

CREATE CAST (agtype[] AS agtype)
WITH FUNCTION ag_catalog.agtype_array_to_agtype(agtype[]);
3 changes: 1 addition & 2 deletions sql/agtype_typecast.sql
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,7 @@ CREATE FUNCTION ag_catalog.age_range(variadic "any")
PARALLEL SAFE
AS 'MODULE_PATHNAME';

CREATE FUNCTION ag_catalog.age_unnest(agtype,
list_comprehension boolean = false)
CREATE FUNCTION ag_catalog.age_unnest(agtype)
RETURNS SETOF agtype
LANGUAGE c
IMMUTABLE
Expand Down
2 changes: 2 additions & 0 deletions src/backend/nodes/ag_nodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ const char *node_names[] = {
"cypher_map_projection",
"cypher_map_projection_element",
"cypher_list",
"cypher_list_comprehension",
"cypher_comparison_aexpr",
"cypher_comparison_boolexpr",
"cypher_string_match",
Expand Down Expand Up @@ -115,6 +116,7 @@ const ExtensibleNodeMethods node_methods[] = {
DEFINE_NODE_METHODS(cypher_map),
DEFINE_NODE_METHODS(cypher_map_projection),
DEFINE_NODE_METHODS(cypher_list),
DEFINE_NODE_METHODS(cypher_list_comprehension),
DEFINE_NODE_METHODS(cypher_comparison_aexpr),
DEFINE_NODE_METHODS(cypher_comparison_boolexpr),
DEFINE_NODE_METHODS(cypher_string_match),
Expand Down
14 changes: 12 additions & 2 deletions src/backend/nodes/cypher_outfuncs.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@ void out_cypher_with(StringInfo str, const ExtensibleNode *node)
DEFINE_AG_NODE(cypher_with);

WRITE_BOOL_FIELD(distinct);
WRITE_BOOL_FIELD(subquery_intermediate);
WRITE_NODE_FIELD(items);
WRITE_NODE_FIELD(order_by);
WRITE_NODE_FIELD(skip);
Expand Down Expand Up @@ -176,9 +175,20 @@ void out_cypher_unwind(StringInfo str, const ExtensibleNode *node)
DEFINE_AG_NODE(cypher_unwind);

WRITE_NODE_FIELD(target);
WRITE_NODE_FIELD(collect);
}

/* serialization function for the cypher_list_comprehension ExtensibleNode. */
void out_cypher_list_comprehension(StringInfo str, const ExtensibleNode *node)
{
DEFINE_AG_NODE(cypher_list_comprehension);

WRITE_STRING_FIELD(varname);
WRITE_NODE_FIELD(expr);
WRITE_NODE_FIELD(where);
WRITE_NODE_FIELD(mapping_expr);
}


/* serialization function for the cypher_delete ExtensibleNode. */
void out_cypher_merge(StringInfo str, const ExtensibleNode *node)
{
Expand Down
Loading