This is an automated email from the ASF dual-hosted git repository.
jgemignani pushed a commit to branch PG12
in repository https://gitbox.apache.org/repos/asf/age.git
The following commit(s) were added to refs/heads/PG12 by this push:
new 4cf7a9ec Remove check for scalar agtypes in unwind (#736)
4cf7a9ec is described below
commit 4cf7a9ec525b412edf3a3831d51762484c64d782
Author: Muhammad Taha Naveed <[email protected]>
AuthorDate: Sat Mar 11 05:51:42 2023 +0500
Remove check for scalar agtypes in unwind (#736)
- Added regression tests for unwind.
---
age--1.1.1.sql | 8 +-
regress/expected/cypher_unwind.out | 155 +++++++++++++++++++++++++++++++++----
regress/sql/cypher_unwind.sql | 92 ++++++++++++++++++++--
src/backend/parser/cypher_clause.c | 2 +-
src/backend/utils/adt/agtype.c | 14 +---
5 files changed, 232 insertions(+), 39 deletions(-)
diff --git a/age--1.1.1.sql b/age--1.1.1.sql
index 304d27db..3ee696d1 100644
--- a/age--1.1.1.sql
+++ b/age--1.1.1.sql
@@ -4166,10 +4166,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';
diff --git a/regress/expected/cypher_unwind.out
b/regress/expected/cypher_unwind.out
index d0a71717..3c454f10 100644
--- a/regress/expected/cypher_unwind.out
+++ b/regress/expected/cypher_unwind.out
@@ -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
-----------+---
@@ -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
@@ -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 [...]
+(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
------------
diff --git a/regress/sql/cypher_unwind.sql b/regress/sql/cypher_unwind.sql
index d1f2d81f..8e8c74bc 100644
--- a/regress/sql/cypher_unwind.sql
+++ b/regress/sql/cypher_unwind.sql
@@ -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', $$
@@ -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);
\ No newline at end of file
diff --git a/src/backend/parser/cypher_clause.c
b/src/backend/parser/cypher_clause.c
index f0e6ba8c..0ef33131 100644
--- a/src/backend/parser/cypher_clause.c
+++ b/src/backend/parser/cypher_clause.c
@@ -1341,7 +1341,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);
diff --git a/src/backend/utils/adt/agtype.c b/src/backend/utils/adt/agtype.c
index 4aa724c2..6e5eaca6 100644
--- a/src/backend/utils/adt/agtype.c
+++ b/src/backend/utils/adt/agtype.c
@@ -10038,14 +10038,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;
@@ -10097,15 +10094,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);