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 */

Reply via email to