You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@age.apache.org by de...@apache.org on 2022/02/03 22:40:48 UTC

[incubator-age] branch master updated: bug-fix: chained union logic

This is an automated email from the ASF dual-hosted git repository.

dehowef pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-age.git


The following commit(s) were added to refs/heads/master by this push:
     new ed283c0  bug-fix: chained union logic
ed283c0 is described below

commit ed283c06b44b990957e3fa21e719eb9dc93e45f3
Author: Dehowe Feng <de...@gmail.com>
AuthorDate: Wed Feb 2 16:42:39 2022 -0800

    bug-fix: chained union logic
    
    fixed bug with chained unions that failed to remove duplicate values
    
    the bug appeared when mixing agtypes and chaining multiple unions
---
 regress/expected/cypher_union.out  | 24 ++++++++++++++++++++----
 regress/sql/cypher_union.sql       | 10 +++++++++-
 src/backend/parser/cypher_clause.c | 13 ++++++++++---
 3 files changed, 39 insertions(+), 8 deletions(-)

diff --git a/regress/expected/cypher_union.out b/regress/expected/cypher_union.out
index 1999721..1931564 100644
--- a/regress/expected/cypher_union.out
+++ b/regress/expected/cypher_union.out
@@ -46,15 +46,15 @@ SELECT * FROM cypher('cypher_union', $$ MATCH (n) RETURN n UNION ALL MATCH (n) R
 SELECT * FROM cypher('cypher_union', $$ MATCH (n) RETURN n UNION RETURN 1 $$) as (a agtype);
                                a                                
 ----------------------------------------------------------------
- 1
  {"id": 281474976710657, "label": "", "properties": {}}::vertex
+ 1
 (2 rows)
 
 SELECT * FROM cypher('cypher_union', $$ MATCH (n) RETURN n UNION RETURN NULL $$) as (a agtype);
                                a                                
 ----------------------------------------------------------------
- 
  {"id": 281474976710657, "label": "", "properties": {}}::vertex
+ 
 (2 rows)
 
 SELECT * FROM cypher('cypher_union', $$ RETURN [1,2,3] UNION RETURN 1 $$) as (a agtype);
@@ -137,10 +137,26 @@ SELECT * FROM cypher('cypher_union', $$MATCH (n) RETURN n UNION MATCH (n) return
 (1 row)
 
 /* scoping */
-SELECT * FROM cypher('cypher_union', $$MATCH (n) RETURN n UNION ALL MATCH (m)  RETURN n$$) AS (result agtype);
+SELECT * FROM cypher('cypher_union', $$MATCH (n) RETURN n UNION ALL MATCH (m) RETURN n$$) AS (result agtype);
 ERROR:  could not find rte for n
-LINE 2: ... $$MATCH (n) RETURN n UNION ALL MATCH (m)  RETURN n$$) AS (r...
+LINE 2: ..., $$MATCH (n) RETURN n UNION ALL MATCH (m) RETURN n$$) AS (r...
                                                              ^
+/*
+ *UNION and UNION ALL, type casting
+ */
+SELECT * FROM cypher('cypher_union', $$ RETURN 1.0::int UNION return 1::float UNION ALL RETURN 2.0::float $$) AS (result agtype);
+ result 
+--------
+ 1
+ 2.0
+(2 rows)
+
+SELECT * FROM cypher('cypher_union', $$ RETURN 1.0::float UNION return 1::int UNION RETURN 1::float $$) AS (result agtype);
+ result 
+--------
+ 1.0
+(1 row)
+
 SELECT drop_graph('cypher_union', true);
 NOTICE:  drop cascades to 2 other objects
 DETAIL:  drop cascades to table cypher_union._ag_label_vertex
diff --git a/regress/sql/cypher_union.sql b/regress/sql/cypher_union.sql
index 4f6ec85..3338ebb 100644
--- a/regress/sql/cypher_union.sql
+++ b/regress/sql/cypher_union.sql
@@ -65,6 +65,14 @@ SELECT * FROM cypher('cypher_union', $$MATCH (n) RETURN n UNION ALL MATCH (n) re
 SELECT * FROM cypher('cypher_union', $$MATCH (n) RETURN n UNION MATCH (n) return n UNION ALL MATCH(n) RETURN n$$) AS (result agtype);
 
 /* scoping */
-SELECT * FROM cypher('cypher_union', $$MATCH (n) RETURN n UNION ALL MATCH (m)  RETURN n$$) AS (result agtype);
+SELECT * FROM cypher('cypher_union', $$MATCH (n) RETURN n UNION ALL MATCH (m) RETURN n$$) AS (result agtype);
+
+/*
+ *UNION and UNION ALL, type casting
+ */
+SELECT * FROM cypher('cypher_union', $$ RETURN 1.0::int UNION return 1::float UNION ALL RETURN 2.0::float $$) AS (result agtype);
+
+SELECT * FROM cypher('cypher_union', $$ RETURN 1.0::float UNION return 1::int UNION RETURN 1::float $$) AS (result agtype);
+
 
 SELECT drop_graph('cypher_union', true);
diff --git a/src/backend/parser/cypher_clause.c b/src/backend/parser/cypher_clause.c
index c540237..151da2d 100644
--- a/src/backend/parser/cypher_clause.c
+++ b/src/backend/parser/cypher_clause.c
@@ -921,17 +921,24 @@ transform_cypher_union_tree(cypher_parsestate *cpstate, cypher_clause *clause,
                 SortGroupClause *grpcl = makeNode(SortGroupClause);
                 Oid sortop;
                 Oid eqop;
-                bool hashable;
+                bool hashable = false;
                 ParseCallbackState pcbstate;
 
                 setup_parser_errposition_callback(&pcbstate, pstate,
                                                   bestlocation);
 
-                /* determine the eqop and optional sortop */
+                /*
+                 * determine the eqop and optional sortop
+                 *
+                 * NOTE: for UNION, we set hashable to false and pass a NULL to
+                 * isHashable in get_sort_group_operators to prevent a logic error
+                 * where UNION fails to exclude duplicate results.
+                 *
+                 */
                 get_sort_group_operators(rescoltype,
                                          false, true, false,
                                          &sortop, &eqop, NULL,
-                                         &hashable);
+                                         NULL);
 
                 cancel_parser_errposition_callback(&pcbstate);