Skip to content

Commit

Permalink
Remove check for scalar agtypes in unwind
Browse files Browse the repository at this point in the history
- Added regression tests for unwind.
  • Loading branch information
MuhammadTahaNaveed committed Mar 10, 2023
1 parent 377e1d7 commit f23dda9
Show file tree
Hide file tree
Showing 5 changed files with 232 additions and 39 deletions.
8 changes: 4 additions & 4 deletions age--1.2.0.sql
Original file line number Diff line number Diff line change
Expand Up @@ -4162,10 +4162,10 @@ IMMUTABLE
PARALLEL SAFE
AS 'MODULE_PATHNAME';

CREATE FUNCTION ag_catalog.age_unnest(agtype, block_types boolean = false)
RETURNS SETOF agtype
LANGUAGE c
IMMUTABLE
CREATE FUNCTION ag_catalog.age_unnest(agtype)
RETURNS SETOF agtype
LANGUAGE c
IMMUTABLE
PARALLEL SAFE
AS 'MODULE_PATHNAME';

Expand Down
155 changes: 141 additions & 14 deletions regress/expected/cypher_unwind.out
Original file line number Diff line number Diff line change
Expand Up @@ -25,25 +25,48 @@ NOTICE: graph "cypher_unwind" has been created

(1 row)

-- Create nodes and relations
SELECT * FROM cypher('cypher_unwind', $$
UNWIND [1, 2, 3] AS i RETURN i
CREATE (n {name: 'node1', a: [1, 2, 3]}),
(m {name: 'node2', a: [4, 5, 6]}),
(o {name: 'node3', a: [7, 8, 9]}),
(n)-[:KNOWS]->(m),
(m)-[:KNOWS]->(o)
$$) as (i agtype);
i
---
1
2
3
(0 rows)

SELECT * FROM cypher('cypher_unwind', $$
MATCH (n)
RETURN n
$$) as (i agtype);
i
-----------------------------------------------------------------------------------------------
{"id": 281474976710657, "label": "", "properties": {"a": [1, 2, 3], "name": "node1"}}::vertex
{"id": 281474976710658, "label": "", "properties": {"a": [4, 5, 6], "name": "node2"}}::vertex
{"id": 281474976710659, "label": "", "properties": {"a": [7, 8, 9], "name": "node3"}}::vertex
(3 rows)

--
-- Test UNWIND clause
--
SELECT * FROM cypher('cypher_unwind', $$
CREATE ({a: [1, 2, 3]}), ({a: [4, 5, 6]})
UNWIND [1, 2, 3] AS i
RETURN i
$$) as (i agtype);
i
---
(0 rows)
1
2
3
(3 rows)

SELECT * FROM cypher('cypher_unwind', $$
MATCH (n) WITH n.a AS a UNWIND a AS i RETURN *
MATCH (n)
WITH n.a AS a
UNWIND a AS i
RETURN *
$$) as (i agtype, j agtype);
i | j
-----------+---
Expand All @@ -53,7 +76,10 @@ $$) as (i agtype, j agtype);
[4, 5, 6] | 4
[4, 5, 6] | 5
[4, 5, 6] | 6
(6 rows)
[7, 8, 9] | 7
[7, 8, 9] | 8
[7, 8, 9] | 9
(9 rows)

SELECT * FROM cypher('cypher_unwind', $$
WITH [[1, 2], [3, 4], 5] AS nested
Expand All @@ -70,17 +96,118 @@ $$) as (i agtype);
5
(5 rows)

-- UNWIND vertices
SELECT * FROM cypher('cypher_unwind', $$
MATCH p=(n)-[:KNOWS]->(m)
UNWIND nodes(p) as node
RETURN node
$$) as (i agtype);
i
-----------------------------------------------------------------------------------------------
{"id": 281474976710657, "label": "", "properties": {"a": [1, 2, 3], "name": "node1"}}::vertex
{"id": 281474976710658, "label": "", "properties": {"a": [4, 5, 6], "name": "node2"}}::vertex
{"id": 281474976710658, "label": "", "properties": {"a": [4, 5, 6], "name": "node2"}}::vertex
{"id": 281474976710659, "label": "", "properties": {"a": [7, 8, 9], "name": "node3"}}::vertex
(4 rows)

SELECT * FROM cypher('cypher_unwind', $$
WITH [{id: 0, label:'', properties:{}}::vertex, {id: 1, label:'', properties:{}}::vertex] as n
UNWIND n as a
SET a.i = 1
RETURN a
MATCH p=(n)-[:KNOWS]->(m)
UNWIND nodes(p) as node
RETURN node.name
$$) as (i agtype);
ERROR: UNWIND clause does not support agtype vertex
i
---------
"node1"
"node2"
"node2"
"node3"
(4 rows)

-- UNWIND edges
SELECT * FROM cypher('cypher_unwind', $$
MATCH p=(n)-[:KNOWS]->(m)
UNWIND relationships(p) as relation
RETURN relation
$$) as (i agtype);
i
---------------------------------------------------------------------------------------------------------------------------
{"id": 844424930131969, "label": "KNOWS", "end_id": 281474976710658, "start_id": 281474976710657, "properties": {}}::edge
{"id": 844424930131970, "label": "KNOWS", "end_id": 281474976710659, "start_id": 281474976710658, "properties": {}}::edge
(2 rows)

SELECT * FROM cypher('cypher_unwind', $$
MATCH p=(n)-[:KNOWS]->(m)
UNWIND relationships(p) as relation
RETURN type(relation)
$$) as (i agtype);
i
---------
"KNOWS"
"KNOWS"
(2 rows)

-- UNWIND paths (vle)
SELECT * FROM cypher('cypher_unwind', $$
MATCH p=({name:'node1'})-[e:KNOWS*]->({name:'node3'})
UNWIND [p] as path
RETURN path
$$) as (i agtype);
i
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
[{"id": 281474976710657, "label": "_ag_label_vertex", "properties": {"a": [1, 2, 3], "name": "node1"}}::vertex, {"id": 844424930131969, "label": "KNOWS", "end_id": 281474976710658, "start_id": 281474976710657, "properties": {}}::edge, {"id": 281474976710658, "label": "_ag_label_vertex", "properties": {"a": [4, 5, 6], "name": "node2"}}::vertex, {"id": 844424930131970, "label": "KNOWS", "end_id": 281474976710659, "start_id": 281474976710658, "properties": {}}::edge, {"id": 281474976710659, "label": "_ag_label_vertex", "properties": {"a": [7, 8, 9], "name": "node3"}}::vertex]::path
(1 row)

SELECT * FROM cypher('cypher_unwind', $$
MATCH p=({name:'node1'})-[e:KNOWS*]->({name:'node3'})
UNWIND [p] as path
RETURN relationships(path)
$$) as (i agtype);
i
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
[{"id": 844424930131969, "label": "KNOWS", "end_id": 281474976710658, "start_id": 281474976710657, "properties": {}}::edge, {"id": 844424930131970, "label": "KNOWS", "end_id": 281474976710659, "start_id": 281474976710658, "properties": {}}::edge]
(1 row)

SELECT * FROM cypher('cypher_unwind', $$
MATCH p=({name:'node1'})-[e:KNOWS*]->({name:'node3'})
UNWIND [p] as path
UNWIND relationships(path) as edge
RETURN edge
$$) as (i agtype);
i
---------------------------------------------------------------------------------------------------------------------------
{"id": 844424930131969, "label": "KNOWS", "end_id": 281474976710658, "start_id": 281474976710657, "properties": {}}::edge
{"id": 844424930131970, "label": "KNOWS", "end_id": 281474976710659, "start_id": 281474976710658, "properties": {}}::edge
(2 rows)

-- Unwind with SET clause
SELECT * FROM cypher('cypher_unwind', $$
MATCH p=(n)-[:KNOWS]->(m)
UNWIND nodes(p) as node
SET node.type = 'vertex'
$$) as (i agtype);
i
---
(0 rows)

SELECT * FROM cypher('cypher_unwind', $$
MATCH (n)
RETURN n
$$) as (i agtype);
i
-----------------------------------------------------------------------------------------------------------------
{"id": 281474976710657, "label": "", "properties": {"a": [1, 2, 3], "name": "node1", "type": "vertex"}}::vertex
{"id": 281474976710658, "label": "", "properties": {"a": [4, 5, 6], "name": "node2", "type": "vertex"}}::vertex
{"id": 281474976710659, "label": "", "properties": {"a": [7, 8, 9], "name": "node3", "type": "vertex"}}::vertex
(3 rows)

--
-- Clean up
--
SELECT drop_graph('cypher_unwind', true);
NOTICE: drop cascades to 2 other objects
NOTICE: drop cascades to 3 other objects
DETAIL: drop cascades to table cypher_unwind._ag_label_vertex
drop cascades to table cypher_unwind._ag_label_edge
drop cascades to table cypher_unwind."KNOWS"
NOTICE: graph "cypher_unwind" has been dropped
drop_graph
------------
Expand Down
92 changes: 85 additions & 7 deletions regress/sql/cypher_unwind.sql
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,35 @@ SET search_path TO ag_catalog;

SELECT create_graph('cypher_unwind');

-- Create nodes and relations

SELECT * FROM cypher('cypher_unwind', $$
UNWIND [1, 2, 3] AS i RETURN i
CREATE (n {name: 'node1', a: [1, 2, 3]}),
(m {name: 'node2', a: [4, 5, 6]}),
(o {name: 'node3', a: [7, 8, 9]}),
(n)-[:KNOWS]->(m),
(m)-[:KNOWS]->(o)
$$) as (i agtype);

SELECT * FROM cypher('cypher_unwind', $$
CREATE ({a: [1, 2, 3]}), ({a: [4, 5, 6]})
MATCH (n)
RETURN n
$$) as (i agtype);

--
-- Test UNWIND clause
--

SELECT * FROM cypher('cypher_unwind', $$
UNWIND [1, 2, 3] AS i
RETURN i
$$) as (i agtype);

SELECT * FROM cypher('cypher_unwind', $$
MATCH (n) WITH n.a AS a UNWIND a AS i RETURN *
MATCH (n)
WITH n.a AS a
UNWIND a AS i
RETURN *
$$) as (i agtype, j agtype);

SELECT * FROM cypher('cypher_unwind', $$
Expand All @@ -41,11 +60,70 @@ SELECT * FROM cypher('cypher_unwind', $$
RETURN y
$$) as (i agtype);

-- UNWIND vertices

SELECT * FROM cypher('cypher_unwind', $$
MATCH p=(n)-[:KNOWS]->(m)
UNWIND nodes(p) as node
RETURN node
$$) as (i agtype);

SELECT * FROM cypher('cypher_unwind', $$
MATCH p=(n)-[:KNOWS]->(m)
UNWIND nodes(p) as node
RETURN node.name
$$) as (i agtype);

-- UNWIND edges

SELECT * FROM cypher('cypher_unwind', $$
MATCH p=(n)-[:KNOWS]->(m)
UNWIND relationships(p) as relation
RETURN relation
$$) as (i agtype);

SELECT * FROM cypher('cypher_unwind', $$
MATCH p=(n)-[:KNOWS]->(m)
UNWIND relationships(p) as relation
RETURN type(relation)
$$) as (i agtype);

-- UNWIND paths (vle)

SELECT * FROM cypher('cypher_unwind', $$
MATCH p=({name:'node1'})-[e:KNOWS*]->({name:'node3'})
UNWIND [p] as path
RETURN path
$$) as (i agtype);

SELECT * FROM cypher('cypher_unwind', $$
MATCH p=({name:'node1'})-[e:KNOWS*]->({name:'node3'})
UNWIND [p] as path
RETURN relationships(path)
$$) as (i agtype);

SELECT * FROM cypher('cypher_unwind', $$
WITH [{id: 0, label:'', properties:{}}::vertex, {id: 1, label:'', properties:{}}::vertex] as n
UNWIND n as a
SET a.i = 1
RETURN a
MATCH p=({name:'node1'})-[e:KNOWS*]->({name:'node3'})
UNWIND [p] as path
UNWIND relationships(path) as edge
RETURN edge
$$) as (i agtype);

-- Unwind with SET clause

SELECT * FROM cypher('cypher_unwind', $$
MATCH p=(n)-[:KNOWS]->(m)
UNWIND nodes(p) as node
SET node.type = 'vertex'
$$) as (i agtype);

SELECT * FROM cypher('cypher_unwind', $$
MATCH (n)
RETURN n
$$) as (i agtype);

--
-- Clean up
--

SELECT drop_graph('cypher_unwind', true);
2 changes: 1 addition & 1 deletion src/backend/parser/cypher_clause.c
Original file line number Diff line number Diff line change
Expand Up @@ -1331,7 +1331,7 @@ static Query *transform_cypher_unwind(cypher_parsestate *cpstate,
old_expr_kind = pstate->p_expr_kind;
pstate->p_expr_kind = EXPR_KIND_SELECT_TARGET;
funcexpr = ParseFuncOrColumn(pstate, unwind->funcname,
list_make2(expr, makeBoolConst(true, false)),
list_make1(expr),
pstate->p_last_srf, unwind, false,
target_syntax_loc);

Expand Down
14 changes: 1 addition & 13 deletions src/backend/utils/adt/agtype.c
Original file line number Diff line number Diff line change
Expand Up @@ -10031,14 +10031,11 @@ Datum age_range(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(age_unnest);
/*
* Function to convert the Array type of Agtype into each row. It is used for
* Cypher `UNWIND` clause, but considering the situation in which the user can
* directly use this function in vanilla PGSQL, put a second parameter related
* to this.
* Cypher `UNWIND` clause.
*/
Datum age_unnest(PG_FUNCTION_ARGS)
{
agtype *agtype_arg = AG_GET_ARG_AGTYPE_P(0);
bool block_types = PG_GETARG_BOOL(1);
ReturnSetInfo *rsi;
Tuplestorestate *tuple_store;
TupleDesc tupdesc;
Expand Down Expand Up @@ -10090,15 +10087,6 @@ Datum age_unnest(PG_FUNCTION_ARGS)
bool nulls[1] = {false};
agtype *val = agtype_value_to_agtype(&v);

if (block_types && (
v.type == AGTV_VERTEX || v.type == AGTV_EDGE || v.type == AGTV_PATH))
{
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("UNWIND clause does not support agtype %s",
agtype_value_type_to_string(v.type))));
}

/* use the tmp context so we can clean up after each tuple is done */
old_cxt = MemoryContextSwitchTo(tmp_cxt);

Expand Down

0 comments on commit f23dda9

Please sign in to comment.