This is an automated email from the ASF dual-hosted git repository.
rafsun42 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/age.git
The following commit(s) were added to refs/heads/master by this push:
new ffc98692 Implement Returnless Unions in Subqueries (#1803)
ffc98692 is described below
commit ffc9869232a6c8d9a824277971bf4dcc4956bedf
Author: Dehowe Feng <[email protected]>
AuthorDate: Sat May 11 01:35:54 2024 +0800
Implement Returnless Unions in Subqueries (#1803)
Added logic to support returnless unions in subqueries.
Added regression tests to support this addition. Modified
regression tests to capture more cases.
---
regress/expected/cypher_subquery.out | 165 ++++++++++++++++++++++-------------
regress/sql/cypher_subquery.sql | 17 +++-
src/backend/nodes/cypher_outfuncs.c | 1 +
src/backend/parser/cypher_clause.c | 7 +-
src/backend/parser/cypher_gram.y | 22 ++++-
src/include/nodes/cypher_nodes.h | 1 +
6 files changed, 143 insertions(+), 70 deletions(-)
diff --git a/regress/expected/cypher_subquery.out
b/regress/expected/cypher_subquery.out
index 559f0c67..ff5672bc 100644
--- a/regress/expected/cypher_subquery.out
+++ b/regress/expected/cypher_subquery.out
@@ -12,7 +12,7 @@ SELECT * FROM cypher('subquery', $$
(:person {name: "Chan", age: 45})<-[:knows]-(:person {name: "Faye", age:
25})-[:knows]->
(:person {name: "Tony", age: 34})-[:loved]->(:person {name : "Valerie", age:
33}),
(:person {name: "Calvin", age: 6})-[:knows]->(:pet {name: "Hobbes"}),
-
(:person {name: "Charlie", age: 8})-[:knows]->(:pet {name : "Snoopy"}),
+
(:person {name: "Lucy", age: 8})<-[:knows]-(:person {name: "Charlie", age:
8})-[:knows]->(:pet {name : "Snoopy"}),
(:pet {name: "Odie"})<-[:knows]-(:person {name: "Jon", age:
29})-[:knows]->(:pet {name: "Garfield"})
$$) AS (result
agtype);
result
@@ -29,13 +29,14 @@ SELECT * FROM cypher('subquery', $$ MATCH (a) RETURN (a)
$$) AS (result agtype);
{"id": 844424930131973, "label": "person", "properties": {"age": 34, "name":
"Tony"}}::vertex
{"id": 844424930131974, "label": "person", "properties": {"age": 33, "name":
"Valerie"}}::vertex
{"id": 844424930131975, "label": "person", "properties": {"age": 6, "name":
"Calvin"}}::vertex
- {"id": 844424930131976, "label": "person", "properties": {"age": 8, "name":
"Charlie"}}::vertex
- {"id": 844424930131977, "label": "person", "properties": {"age": 29, "name":
"Jon"}}::vertex
+ {"id": 844424930131976, "label": "person", "properties": {"age": 8, "name":
"Lucy"}}::vertex
+ {"id": 844424930131977, "label": "person", "properties": {"age": 8, "name":
"Charlie"}}::vertex
+ {"id": 844424930131978, "label": "person", "properties": {"age": 29, "name":
"Jon"}}::vertex
{"id": 1688849860263937, "label": "pet", "properties": {"name":
"Hobbes"}}::vertex
{"id": 1688849860263938, "label": "pet", "properties": {"name":
"Snoopy"}}::vertex
{"id": 1688849860263939, "label": "pet", "properties": {"name":
"Odie"}}::vertex
{"id": 1688849860263940, "label": "pet", "properties": {"name":
"Garfield"}}::vertex
-(13 rows)
+(14 rows)
SELECT * FROM cypher('subquery', $$ MATCH (a:person)
WHERE
EXISTS {(a:person)-[]->(:pet)}
@@ -43,8 +44,8 @@ SELECT * FROM cypher('subquery', $$ MATCH (a:person)
result
-------------------------------------------------------------------------------------------------
{"id": 844424930131975, "label": "person", "properties": {"age": 6, "name":
"Calvin"}}::vertex
- {"id": 844424930131976, "label": "person", "properties": {"age": 8, "name":
"Charlie"}}::vertex
- {"id": 844424930131977, "label": "person", "properties": {"age": 29, "name":
"Jon"}}::vertex
+ {"id": 844424930131977, "label": "person", "properties": {"age": 8, "name":
"Charlie"}}::vertex
+ {"id": 844424930131978, "label": "person", "properties": {"age": 29, "name":
"Jon"}}::vertex
(3 rows)
--trying to use b when not defined, should create pattern
@@ -54,8 +55,8 @@ SELECT * FROM cypher('subquery', $$ MATCH (a:person)
result
-------------------------------------------------------------------------------------------------
{"id": 844424930131975, "label": "person", "properties": {"age": 6, "name":
"Calvin"}}::vertex
- {"id": 844424930131976, "label": "person", "properties": {"age": 8, "name":
"Charlie"}}::vertex
- {"id": 844424930131977, "label": "person", "properties": {"age": 29, "name":
"Jon"}}::vertex
+ {"id": 844424930131977, "label": "person", "properties": {"age": 8, "name":
"Charlie"}}::vertex
+ {"id": 844424930131978, "label": "person", "properties": {"age": 29, "name":
"Jon"}}::vertex
(3 rows)
--query inside
@@ -65,8 +66,8 @@ SELECT * FROM cypher('subquery', $$ MATCH (a:person)
result
-------------------------------------------------------------------------------------------------
{"id": 844424930131975, "label": "person", "properties": {"age": 6, "name":
"Calvin"}}::vertex
- {"id": 844424930131976, "label": "person", "properties": {"age": 8, "name":
"Charlie"}}::vertex
- {"id": 844424930131977, "label": "person", "properties": {"age": 29, "name":
"Jon"}}::vertex
+ {"id": 844424930131977, "label": "person", "properties": {"age": 8, "name":
"Charlie"}}::vertex
+ {"id": 844424930131978, "label": "person", "properties": {"age": 29, "name":
"Jon"}}::vertex
(3 rows)
--repeat variable in match
@@ -134,18 +135,36 @@ SELECT * FROM cypher('subquery', $$ MATCH (a:person)
ERROR: could not find rte for c
LINE 5: RETURN c
^
---union, no returns, not yet implemented, should error out
+--union, no returns
SELECT * FROM cypher('subquery', $$ MATCH (a:person)
WHERE
EXISTS {
MATCH (a:person)-[]->(b:pet)
WHERE a.name = 'Charlie'
UNION
-
MATCH (c:person)-[]->(d:person)
+
MATCH (a:person)-[]->(c:person)
}
RETURN
(a) $$) AS (result agtype);
-ERROR: Subquery UNION without returns not yet implemented
-LINE 5: UNION
- ^
+ result
+---------------------------------------------------------------------------------------------------
+ {"id": 844424930131969, "label": "person", "properties": {"age": 32, "name":
"Briggite"}}::vertex
+ {"id": 844424930131972, "label": "person", "properties": {"age": 25, "name":
"Faye"}}::vertex
+ {"id": 844424930131973, "label": "person", "properties": {"age": 34, "name":
"Tony"}}::vertex
+ {"id": 844424930131977, "label": "person", "properties": {"age": 8, "name":
"Charlie"}}::vertex
+(4 rows)
+
+--union, mismatched number of return columns for returns
+SELECT * FROM cypher('subquery', $$ MATCH (a:person)
+ WHERE
EXISTS {
+
MATCH (a:person)-[]->(b:pet)
+
RETURN a, b
+
UNION
+
MATCH (a:person)-[]->(c:person)
+
RETURN c
+
}
+ RETURN
(a) $$) AS (result agtype);
+ERROR: each UNION query must have the same number of columns
+LINE 7: RETURN c
+ ^
--union, only one has return, should fail
SELECT * FROM cypher('subquery', $$ MATCH (a:person)
WHERE
EXISTS {
@@ -180,9 +199,10 @@ SELECT * FROM cypher('subquery', $$ MATCH (a:person)
{"id": 844424930131973, "label": "person", "properties": {"age": 34, "name":
"Tony"}}::vertex
{"id": 844424930131974, "label": "person", "properties": {"age": 33, "name":
"Valerie"}}::vertex
{"id": 844424930131975, "label": "person", "properties": {"age": 6, "name":
"Calvin"}}::vertex
- {"id": 844424930131976, "label": "person", "properties": {"age": 8, "name":
"Charlie"}}::vertex
- {"id": 844424930131977, "label": "person", "properties": {"age": 29, "name":
"Jon"}}::vertex
-(9 rows)
+ {"id": 844424930131976, "label": "person", "properties": {"age": 8, "name":
"Lucy"}}::vertex
+ {"id": 844424930131977, "label": "person", "properties": {"age": 8, "name":
"Charlie"}}::vertex
+ {"id": 844424930131978, "label": "person", "properties": {"age": 29, "name":
"Jon"}}::vertex
+(10 rows)
--nesting same var multiple layers
SELECT * FROM cypher('subquery', $$ MATCH (a:person)
@@ -218,13 +238,14 @@ SELECT * FROM cypher('subquery', $$ MATCH (a)
{"id": 844424930131973, "label": "person", "properties": {"age": 34, "name":
"Tony"}}::vertex
{"id": 844424930131974, "label": "person", "properties": {"age": 33, "name":
"Valerie"}}::vertex
{"id": 844424930131975, "label": "person", "properties": {"age": 6, "name":
"Calvin"}}::vertex
- {"id": 844424930131976, "label": "person", "properties": {"age": 8, "name":
"Charlie"}}::vertex
- {"id": 844424930131977, "label": "person", "properties": {"age": 29, "name":
"Jon"}}::vertex
+ {"id": 844424930131976, "label": "person", "properties": {"age": 8, "name":
"Lucy"}}::vertex
+ {"id": 844424930131977, "label": "person", "properties": {"age": 8, "name":
"Charlie"}}::vertex
+ {"id": 844424930131978, "label": "person", "properties": {"age": 29, "name":
"Jon"}}::vertex
{"id": 1688849860263937, "label": "pet", "properties": {"name":
"Hobbes"}}::vertex
{"id": 1688849860263938, "label": "pet", "properties": {"name":
"Snoopy"}}::vertex
{"id": 1688849860263939, "label": "pet", "properties": {"name":
"Odie"}}::vertex
{"id": 1688849860263940, "label": "pet", "properties": {"name":
"Garfield"}}::vertex
-(13 rows)
+(14 rows)
--nesting, accessing indirection in outer scope
SELECT * FROM cypher('subquery', $$ MATCH (a:person)
@@ -246,9 +267,10 @@ SELECT * FROM cypher('subquery', $$ MATCH (a:person)
{"id": 844424930131973, "label": "person", "properties": {"age": 34, "name":
"Tony"}}::vertex
{"id": 844424930131974, "label": "person", "properties": {"age": 33, "name":
"Valerie"}}::vertex
{"id": 844424930131975, "label": "person", "properties": {"age": 6, "name":
"Calvin"}}::vertex
- {"id": 844424930131976, "label": "person", "properties": {"age": 8, "name":
"Charlie"}}::vertex
- {"id": 844424930131977, "label": "person", "properties": {"age": 29, "name":
"Jon"}}::vertex
-(9 rows)
+ {"id": 844424930131976, "label": "person", "properties": {"age": 8, "name":
"Lucy"}}::vertex
+ {"id": 844424930131977, "label": "person", "properties": {"age": 8, "name":
"Charlie"}}::vertex
+ {"id": 844424930131978, "label": "person", "properties": {"age": 29, "name":
"Jon"}}::vertex
+(10 rows)
--nesting, accessing var 2+ levels up
SELECT * FROM cypher('subquery', $$ MATCH (a:person)
@@ -286,9 +308,10 @@ SELECT * FROM cypher('subquery', $$ MATCH (a:person)
{"id": 844424930131973, "label": "person", "properties": {"age": 34, "name":
"Tony"}}::vertex
{"id": 844424930131974, "label": "person", "properties": {"age": 33, "name":
"Valerie"}}::vertex
{"id": 844424930131975, "label": "person", "properties": {"age": 6, "name":
"Calvin"}}::vertex
- {"id": 844424930131976, "label": "person", "properties": {"age": 8, "name":
"Charlie"}}::vertex
- {"id": 844424930131977, "label": "person", "properties": {"age": 29, "name":
"Jon"}}::vertex
-(9 rows)
+ {"id": 844424930131976, "label": "person", "properties": {"age": 8, "name":
"Lucy"}}::vertex
+ {"id": 844424930131977, "label": "person", "properties": {"age": 8, "name":
"Charlie"}}::vertex
+ {"id": 844424930131978, "label": "person", "properties": {"age": 29, "name":
"Jon"}}::vertex
+(10 rows)
--EXISTS outside of WHERE
SELECT * FROM cypher('subquery', $$ MATCH (a:person)
@@ -303,9 +326,10 @@ SELECT * FROM cypher('subquery', $$ MATCH (a:person)
{"id": 844424930131973, "label": "person", "properties": {"age": 34, "name":
"Tony"}}::vertex | false
{"id": 844424930131974, "label": "person", "properties": {"age": 33, "name":
"Valerie"}}::vertex | false
{"id": 844424930131975, "label": "person", "properties": {"age": 6, "name":
"Calvin"}}::vertex | true
- {"id": 844424930131976, "label": "person", "properties": {"age": 8, "name":
"Charlie"}}::vertex | true
- {"id": 844424930131977, "label": "person", "properties": {"age": 29, "name":
"Jon"}}::vertex | true
-(9 rows)
+ {"id": 844424930131976, "label": "person", "properties": {"age": 8, "name":
"Lucy"}}::vertex | false
+ {"id": 844424930131977, "label": "person", "properties": {"age": 8, "name":
"Charlie"}}::vertex | true
+ {"id": 844424930131978, "label": "person", "properties": {"age": 29, "name":
"Jon"}}::vertex | true
+(10 rows)
--Var doesnt exist in outside scope, should fail
SELECT * FROM cypher('subquery', $$ RETURN 1,
@@ -338,9 +362,10 @@ SELECT * FROM cypher('subquery', $$ MATCH (a:person)
0
0
1
+ 0
1
2
-(9 rows)
+(10 rows)
--count pattern with WHERE
SELECT * FROM cypher('subquery', $$ MATCH (a:person)
@@ -358,18 +383,20 @@ SELECT * FROM cypher('subquery', $$ MATCH (a:person)
1
0
0
-(9 rows)
+ 0
+(10 rows)
--solo match in where
SELECT * FROM cypher('subquery', $$ MATCH (a:person)
WHERE
COUNT{MATCH (a:person)-[]-()} > 1
RETURN
a $$) AS (result agtype);
- result
------------------------------------------------------------------------------------------------
+ result
+-------------------------------------------------------------------------------------------------
{"id": 844424930131972, "label": "person", "properties": {"age": 25, "name":
"Faye"}}::vertex
{"id": 844424930131973, "label": "person", "properties": {"age": 34, "name":
"Tony"}}::vertex
- {"id": 844424930131977, "label": "person", "properties": {"age": 29, "name":
"Jon"}}::vertex
-(3 rows)
+ {"id": 844424930131977, "label": "person", "properties": {"age": 8, "name":
"Charlie"}}::vertex
+ {"id": 844424930131978, "label": "person", "properties": {"age": 29, "name":
"Jon"}}::vertex
+(4 rows)
--match where person has more than one pet
SELECT * FROM cypher('subquery', $$ MATCH (a:person)
@@ -377,25 +404,26 @@ SELECT * FROM cypher('subquery', $$ MATCH (a:person)
RETURN
a $$) AS (result agtype);
result
----------------------------------------------------------------------------------------------
- {"id": 844424930131977, "label": "person", "properties": {"age": 29, "name":
"Jon"}}::vertex
+ {"id": 844424930131978, "label": "person", "properties": {"age": 29, "name":
"Jon"}}::vertex
(1 row)
--match on labels
SELECT * FROM cypher('subquery', $$ MATCH (a:person)
WHERE
COUNT{MATCH (a:person)-[:knows]-()} > 1
RETURN
a $$) AS (result agtype);
- result
------------------------------------------------------------------------------------------------
+ result
+-------------------------------------------------------------------------------------------------
{"id": 844424930131972, "label": "person", "properties": {"age": 25, "name":
"Faye"}}::vertex
- {"id": 844424930131977, "label": "person", "properties": {"age": 29, "name":
"Jon"}}::vertex
-(2 rows)
+ {"id": 844424930131977, "label": "person", "properties": {"age": 8, "name":
"Charlie"}}::vertex
+ {"id": 844424930131978, "label": "person", "properties": {"age": 29, "name":
"Jon"}}::vertex
+(3 rows)
SELECT * FROM cypher('subquery', $$ MATCH (a:person)
WHERE
COUNT{MATCH (a:person)-[:knows]-(:pet)} > 1
RETURN
a $$) AS (result agtype);
result
----------------------------------------------------------------------------------------------
- {"id": 844424930131977, "label": "person", "properties": {"age": 29, "name":
"Jon"}}::vertex
+ {"id": 844424930131978, "label": "person", "properties": {"age": 29, "name":
"Jon"}}::vertex
(1 row)
SELECT * FROM cypher('subquery', $$ MATCH (a:person)
@@ -420,7 +448,8 @@ SELECT * FROM cypher('subquery', $$ MATCH (a:person)
1
1
1
-(9 rows)
+ 1
+(10 rows)
--match return in where
SELECT * FROM cypher('subquery', $$ MATCH (a:person)
@@ -443,7 +472,8 @@ SELECT * FROM cypher('subquery', $$ MATCH (a:person)
1
1
1
-(9 rows)
+ 1
+(10 rows)
--match where return
SELECT * FROM cypher('subquery', $$ MATCH (a:person)
@@ -460,9 +490,10 @@ SELECT * FROM cypher('subquery', $$ MATCH (a:person)
"Tony" | 34 | 1
"Valerie" | 33 | 1
"Calvin" | 6 | 0
+ "Lucy" | 8 | 0
"Charlie" | 8 | 0
"Jon" | 29 | 1
-(9 rows)
+(10 rows)
--counting number of relationships per node
SELECT * FROM cypher('subquery', $$ MATCH (a:person)
@@ -476,9 +507,10 @@ SELECT * FROM cypher('subquery', $$ MATCH (a:person)
"Tony" | 2
"Valerie" | 1
"Calvin" | 1
- "Charlie" | 1
+ "Lucy" | 1
+ "Charlie" | 2
"Jon" | 2
-(9 rows)
+(10 rows)
--nested counts
SELECT * FROM cypher('subquery', $$ MATCH (a:person)
@@ -496,9 +528,10 @@ SELECT * FROM cypher('subquery', $$ MATCH (a:person)
"Tony" | 0
"Valerie" | 0
"Calvin" | 1
+ "Lucy" | 1
"Charlie" | 1
"Jon" | 0
-(9 rows)
+(10 rows)
--incorrect variable reference
SELECT * FROM cypher('subquery', $$ MATCH (a:person)
@@ -531,9 +564,10 @@ SELECT * FROM cypher('subquery', $$ MATCH (a:person)
"Tony" | 0
"Valerie" | 0
"Calvin" | 1
+ "Lucy" | 0
"Charlie" | 1
"Jon" | 1
-(9 rows)
+(10 rows)
--
-- expression tree walker additional tests. want to test the nesting
capabilties of the expr tree walker
@@ -559,8 +593,8 @@ SELECT * FROM cypher('subquery', $$ MATCH (a:person)
{"id": 844424930131972, "label": "person", "properties": {"age": 25, "name":
"Faye"}}::vertex
{"id": 844424930131973, "label": "person", "properties": {"age": 34, "name":
"Tony"}}::vertex
{"id": 844424930131975, "label": "person", "properties": {"age": 6, "name":
"Calvin"}}::vertex
- {"id": 844424930131976, "label": "person", "properties": {"age": 8, "name":
"Charlie"}}::vertex
- {"id": 844424930131977, "label": "person", "properties": {"age": 29, "name":
"Jon"}}::vertex
+ {"id": 844424930131977, "label": "person", "properties": {"age": 8, "name":
"Charlie"}}::vertex
+ {"id": 844424930131978, "label": "person", "properties": {"age": 29, "name":
"Jon"}}::vertex
(6 rows)
-- Nested BoolExpr
@@ -569,9 +603,10 @@ SELECT * FROM cypher('subquery', $$ MATCH (a:person)
WHERE
a.name = 'Charlie'}
AND
EXISTS {(a:person)-[]->(:person)}
RETURN
(a) $$) AS (result agtype);
- result
---------
-(0 rows)
+ result
+-------------------------------------------------------------------------------------------------
+ {"id": 844424930131977, "label": "person", "properties": {"age": 8, "name":
"Charlie"}}::vertex
+(1 row)
-- CaseExpr
-- subqueries in WHEN statement in RETURN
@@ -590,11 +625,12 @@ SELECT * FROM cypher('subquery', $$ MATCH
(a:person)-[]->(b)
"Faye" | "Chan" | "There is a relationship"
"Faye" | "Tony" | "There is a relationship"
"Tony" | "Valerie" | "There is LOVE!!!!!!"
+ "Charlie" | "Lucy" | "There is a relationship"
"Calvin" | "Hobbes" | "There is a relationship"
"Charlie" | "Snoopy" | "There is a relationship"
"Jon" | "Odie" | "There is a relationship"
"Jon" | "Garfield" | "There is a relationship"
-(8 rows)
+(9 rows)
-- subqueries in THEN, WHERE
SELECT * FROM cypher('subquery', $$ MATCH (a:person)-[]->(b)
@@ -607,8 +643,8 @@ SELECT * FROM cypher('subquery', $$ MATCH (a:person)-[]->(b)
result
-----------------------------------------------------------------------------------------------
{"id": 844424930131973, "label": "person", "properties": {"age": 34, "name":
"Tony"}}::vertex
- {"id": 844424930131977, "label": "person", "properties": {"age": 29, "name":
"Jon"}}::vertex
- {"id": 844424930131977, "label": "person", "properties": {"age": 29, "name":
"Jon"}}::vertex
+ {"id": 844424930131978, "label": "person", "properties": {"age": 29, "name":
"Jon"}}::vertex
+ {"id": 844424930131978, "label": "person", "properties": {"age": 29, "name":
"Jon"}}::vertex
(3 rows)
-- nested in another exists
@@ -633,8 +669,9 @@ SELECT * FROM cypher('subquery', $$ MATCH (a:person)-[]->(b)
result
-------------------------------------------------------------------------------------------------
{"id": 844424930131975, "label": "person", "properties": {"age": 6, "name":
"Calvin"}}::vertex
- {"id": 844424930131976, "label": "person", "properties": {"age": 8, "name":
"Charlie"}}::vertex
-(2 rows)
+ {"id": 844424930131977, "label": "person", "properties": {"age": 8, "name":
"Charlie"}}::vertex
+ {"id": 844424930131977, "label": "person", "properties": {"age": 8, "name":
"Charlie"}}::vertex
+(3 rows)
--coalesce, nested in return
SELECT * FROM cypher('subquery', $$ MATCH (a:person)-[]->(b)
@@ -674,13 +711,14 @@ SELECT * FROM cypher('subquery', $$MATCH (a)
{"id": 844424930131973, "label": "person", "properties": {"age": 34, "name":
"Tony"}}::vertex | false
{"id": 844424930131974, "label": "person", "properties": {"age": 33, "name":
"Valerie"}}::vertex | false
{"id": 844424930131975, "label": "person", "properties": {"age": 6, "name":
"Calvin"}}::vertex | false
- {"id": 844424930131976, "label": "person", "properties": {"age": 8, "name":
"Charlie"}}::vertex | false
- {"id": 844424930131977, "label": "person", "properties": {"age": 29, "name":
"Jon"}}::vertex | false
+ {"id": 844424930131976, "label": "person", "properties": {"age": 8, "name":
"Lucy"}}::vertex | false
+ {"id": 844424930131977, "label": "person", "properties": {"age": 8, "name":
"Charlie"}}::vertex | false
+ {"id": 844424930131978, "label": "person", "properties": {"age": 29, "name":
"Jon"}}::vertex | false
{"id": 1688849860263937, "label": "pet", "properties": {"name":
"Hobbes"}}::vertex | true
{"id": 1688849860263938, "label": "pet", "properties": {"name":
"Snoopy"}}::vertex | true
{"id": 1688849860263939, "label": "pet", "properties": {"name":
"Odie"}}::vertex | true
{"id": 1688849860263940, "label": "pet", "properties": {"name":
"Garfield"}}::vertex | true
-(13 rows)
+(14 rows)
-- map projection
--where
@@ -706,13 +744,14 @@ SELECT * FROM cypher('subquery', $$MATCH (a)
"Tony" | {"a": false}
"Valerie" | {"a": false}
"Calvin" | {"a": false}
+ "Lucy" | {"a": false}
"Charlie" | {"a": false}
"Jon" | {"a": false}
"Hobbes" | {"a": false}
"Snoopy" | {"a": false}
"Odie" | {"a": false}
"Garfield" | {"a": false}
-(13 rows)
+(14 rows)
--lists
--list
diff --git a/regress/sql/cypher_subquery.sql b/regress/sql/cypher_subquery.sql
index 1f10435a..43c4db53 100644
--- a/regress/sql/cypher_subquery.sql
+++ b/regress/sql/cypher_subquery.sql
@@ -8,7 +8,7 @@ SELECT * FROM cypher('subquery', $$
(:person {name: "Chan", age: 45})<-[:knows]-(:person {name: "Faye", age:
25})-[:knows]->
(:person {name: "Tony", age: 34})-[:loved]->(:person {name : "Valerie", age:
33}),
(:person {name: "Calvin", age: 6})-[:knows]->(:pet {name: "Hobbes"}),
-
(:person {name: "Charlie", age: 8})-[:knows]->(:pet {name : "Snoopy"}),
+
(:person {name: "Lucy", age: 8})<-[:knows]-(:person {name: "Charlie", age:
8})-[:knows]->(:pet {name : "Snoopy"}),
(:pet {name: "Odie"})<-[:knows]-(:person {name: "Jon", age:
29})-[:knows]->(:pet {name: "Garfield"})
$$) AS (result
agtype);
@@ -73,13 +73,24 @@ SELECT * FROM cypher('subquery', $$ MATCH (a:person)
}
RETURN
(a) $$) AS (result agtype);
---union, no returns, not yet implemented, should error out
+--union, no returns
SELECT * FROM cypher('subquery', $$ MATCH (a:person)
WHERE
EXISTS {
MATCH (a:person)-[]->(b:pet)
WHERE a.name = 'Charlie'
UNION
-
MATCH (c:person)-[]->(d:person)
+
MATCH (a:person)-[]->(c:person)
+
}
+ RETURN
(a) $$) AS (result agtype);
+
+--union, mismatched number of return columns for returns
+SELECT * FROM cypher('subquery', $$ MATCH (a:person)
+ WHERE
EXISTS {
+
MATCH (a:person)-[]->(b:pet)
+
RETURN a, b
+
UNION
+
MATCH (a:person)-[]->(c:person)
+
RETURN c
}
RETURN
(a) $$) AS (result agtype);
diff --git a/src/backend/nodes/cypher_outfuncs.c
b/src/backend/nodes/cypher_outfuncs.c
index 662d7847..29dc2ce2 100644
--- a/src/backend/nodes/cypher_outfuncs.c
+++ b/src/backend/nodes/cypher_outfuncs.c
@@ -105,6 +105,7 @@ void out_cypher_return(StringInfo str, const ExtensibleNode
*node)
WRITE_NODE_FIELD(limit);
WRITE_BOOL_FIELD(all_or_distinct);
+ WRITE_BOOL_FIELD(returnless_union);
WRITE_ENUM_FIELD(op, SetOperation);
WRITE_NODE_FIELD(larg);
WRITE_NODE_FIELD(rarg);
diff --git a/src/backend/parser/cypher_clause.c
b/src/backend/parser/cypher_clause.c
index d2df8fc8..1cbde9a2 100644
--- a/src/backend/parser/cypher_clause.c
+++ b/src/backend/parser/cypher_clause.c
@@ -800,6 +800,8 @@ transform_cypher_union_tree(cypher_parsestate *cpstate,
cypher_clause *clause,
/*
* Extract a list of the non-junk TLEs for upper-level processing.
*/
+
+ //mechanism to check for top level query list items here?
if (targetlist)
{
*targetlist = NIL;
@@ -880,8 +882,11 @@ transform_cypher_union_tree(cypher_parsestate *cpstate,
cypher_clause *clause,
/*
* Verify that the two children have the same number of non-junk
* columns, and determine the types of the merged output columns.
+ * If we are in a returnless subquery, we do not care about the columns
+ * matching, because they are not relevant to the end result.
*/
- if (list_length(ltargetlist) != list_length(rtargetlist))
+ if (list_length(ltargetlist) != list_length(rtargetlist) &&
+ self->returnless_union == false)
{
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
diff --git a/src/backend/parser/cypher_gram.y b/src/backend/parser/cypher_gram.y
index a0a6c35f..d6637193 100644
--- a/src/backend/parser/cypher_gram.y
+++ b/src/backend/parser/cypher_gram.y
@@ -242,6 +242,10 @@ static FuncCall *node_to_agtype(Node* fnode, char *type,
int location);
// setops
static Node *make_set_op(SetOperation op, bool all_or_distinct, List *larg,
List *rarg);
+static Node *make_subquery_returnless_set_op(SetOperation op,
+ bool all_or_distinct,
+ List *larg,
+ List *rarg);
// VLE
static cypher_relationship *build_VLE_relation(List *left_arg,
@@ -647,9 +651,7 @@ subquery_stmt_no_return:
}
| subquery_stmt_no_return UNION all_or_distinct subquery_stmt_no_return
{
- ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("Subquery UNION without returns not yet implemented"),
- ag_scanner_errposition(@2, scanner)));
+ $$ = list_make1(make_subquery_returnless_set_op(SETOP_UNION, $3,
$1, $4));
}
;
@@ -2972,6 +2974,20 @@ static Node *make_set_op(SetOperation op, bool
all_or_distinct, List *larg,
return (Node *) n;
}
+/*set operation function node to make a returnless set op node for subqueries*/
+static Node *make_subquery_returnless_set_op(SetOperation op, bool
all_or_distinct, List *larg,
+ List *rarg)
+{
+ cypher_return *n = make_ag_node(cypher_return);
+
+ n->op = op;
+ n->all_or_distinct = all_or_distinct;
+ n->returnless_union = true;
+ n->larg = (List *) larg;
+ n->rarg = (List *) rarg;
+ return (Node *) n;
+}
+
/* check if A_Expr is a comparison expression */
static bool is_A_Expr_a_comparison_operation(cypher_comparison_aexpr *a)
{
diff --git a/src/include/nodes/cypher_nodes.h b/src/include/nodes/cypher_nodes.h
index a64f5a00..5234417a 100644
--- a/src/include/nodes/cypher_nodes.h
+++ b/src/include/nodes/cypher_nodes.h
@@ -58,6 +58,7 @@ typedef struct cypher_return
Node *limit;
bool all_or_distinct;
+ bool returnless_union;
SetOperation op;
List *larg; /* lefthand argument of the unions */
List *rarg; /*righthand argument of the unions */