You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@age.apache.org by jg...@apache.org on 2022/01/27 01:32:24 UTC

[incubator-age] branch master updated: Allow a path of one vertex

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

jgemignani 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 9fdfe40  Allow a path of one vertex
9fdfe40 is described below

commit 9fdfe40f25d665dda603d1fa0ca1eb708baa7540
Author: John Gemignani <jr...@gmail.com>
AuthorDate: Tue Jan 25 15:59:07 2022 -0800

    Allow a path of one vertex
    
    Add in the logic to allow a path of one vertex. This will bring AGE
    paths in line with others who use the openCypher specification,
    namely, Neo4j.
    
    Adjust regression tests.
---
 regress/expected/agtype.out        |  6 ++----
 regress/expected/cypher_create.out | 11 ++++++-----
 regress/expected/cypher_match.out  | 24 +++++++++++++++++++-----
 regress/sql/cypher_create.sql      |  2 +-
 regress/sql/cypher_match.sql       |  2 +-
 src/backend/parser/cypher_clause.c | 14 ++++++--------
 src/backend/utils/adt/agtype.c     | 22 +++++++++++++++-------
 7 files changed, 50 insertions(+), 31 deletions(-)

diff --git a/regress/expected/agtype.out b/regress/expected/agtype.out
index 8647055..cada21f 100644
--- a/regress/expected/agtype.out
+++ b/regress/expected/agtype.out
@@ -2378,8 +2378,7 @@ SELECT _agtype_build_path(
 	_agtype_build_edge('1'::graphid, '2'::graphid, '3'::graphid,
 			  $$label$$, agtype_build_map('id', 2))
 );
-ERROR:  paths consist of alternating vertices and edges
-HINT:  paths require at least 2 vertices and 1 edge
+ERROR:  a path is of the form: [vertex, (edge, vertex)*i] where i >= 0
 SELECT _agtype_build_path(
        _agtype_build_vertex('2'::graphid, $$label_name$$, agtype_build_map()),
        _agtype_build_edge('1'::graphid, '2'::graphid, '3'::graphid,
@@ -2388,8 +2387,7 @@ SELECT _agtype_build_path(
        _agtype_build_edge('1'::graphid, '4'::graphid, '5'::graphid,
                          $$label$$, agtype_build_map('id', 2))
 );
-ERROR:  paths consist of alternating vertices and edges
-HINT:  paths require an odd number of elements
+ERROR:  a path is of the form: [vertex, (edge, vertex)*i] where i >= 0
 SELECT _agtype_build_path(
 	_agtype_build_vertex('2'::graphid, $$label_name$$, agtype_build_map()),
 	_agtype_build_edge('1'::graphid, '2'::graphid, '3'::graphid,
diff --git a/regress/expected/cypher_create.out b/regress/expected/cypher_create.out
index c2aeac6..fb92a37 100644
--- a/regress/expected/cypher_create.out
+++ b/regress/expected/cypher_create.out
@@ -518,15 +518,16 @@ $$) as (a agtype);
 ERROR:  variable b already exists
 LINE 1: SELECT * FROM cypher('cypher_create', $$
                                                ^
--- Not a valid path
+-- A valid single vertex path
 SELECT * FROM cypher('cypher_create', $$
 	CREATE p=(a)
 	RETURN p
 $$) as (a agtype);
-ERROR:  paths consist of alternating vertices and edges.
-LINE 2:  CREATE p=(a)
-                  ^
-HINT:  paths require at least 2 vertices and 1 edge
+                                   a                                    
+------------------------------------------------------------------------
+ [{"id": 281474976710677, "label": "", "properties": {}}::vertex]::path
+(1 row)
+
 --CREATE with joins
 SELECT *
 FROM cypher('cypher_create', $$
diff --git a/regress/expected/cypher_match.out b/regress/expected/cypher_match.out
index e334523..d2d387c 100644
--- a/regress/expected/cypher_match.out
+++ b/regress/expected/cypher_match.out
@@ -528,15 +528,29 @@ ERROR:  label vmissing does not exists
 LINE 1: SELECT * FROM cypher('cypher_match', $$MATCH (n:vmissing)-[]...
                                                      ^
 --
---Errors
+-- Path of one vertex. This should select 14
 --
 SELECT * FROM cypher('cypher_match', $$
        MATCH p=() RETURN p
 $$) AS (p agtype);
-ERROR:  paths consist of alternating vertices and edges.
-LINE 2:        MATCH p=() RETURN p
-                       ^
-HINT:  paths require at least 2 vertices and 1 edge
+                                                                                        p                                                                                        
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ [{"id": 281474976710657, "label": "", "properties": {"int_key": 1, "map_key": {"key": "value"}, "list_key": [1, 2, 3], "float_key": 3.14, "string_key": "test"}}::vertex]::path
+ [{"id": 281474976710658, "label": "", "properties": {"lst": [1, null, 3.14, "string", {"key": "value"}, []]}}::vertex]::path
+ [{"id": 844424930131969, "label": "v", "properties": {}}::vertex]::path
+ [{"id": 844424930131970, "label": "v", "properties": {"i": 0}}::vertex]::path
+ [{"id": 844424930131971, "label": "v", "properties": {"i": 1}}::vertex]::path
+ [{"id": 1125899906842625, "label": "v1", "properties": {"id": "initial"}}::vertex]::path
+ [{"id": 1125899906842626, "label": "v1", "properties": {"id": "middle"}}::vertex]::path
+ [{"id": 1125899906842627, "label": "v1", "properties": {"id": "end"}}::vertex]::path
+ [{"id": 1688849860263937, "label": "v2", "properties": {"id": "initial"}}::vertex]::path
+ [{"id": 1688849860263938, "label": "v2", "properties": {"id": "middle"}}::vertex]::path
+ [{"id": 1688849860263939, "label": "v2", "properties": {"id": "end"}}::vertex]::path
+ [{"id": 2251799813685249, "label": "v3", "properties": {"id": "initial"}}::vertex]::path
+ [{"id": 2251799813685250, "label": "v3", "properties": {"id": "middle"}}::vertex]::path
+ [{"id": 2251799813685251, "label": "v3", "properties": {"id": "end"}}::vertex]::path
+(14 rows)
+
 --
 -- MATCH with WHERE EXISTS(pattern)
 --
diff --git a/regress/sql/cypher_create.sql b/regress/sql/cypher_create.sql
index 7a0051b..62b7d16 100644
--- a/regress/sql/cypher_create.sql
+++ b/regress/sql/cypher_create.sql
@@ -231,7 +231,7 @@ SELECT * FROM cypher('cypher_create', $$
 	CREATE (a)-[b:e_var]->()
 $$) as (a agtype);
 
--- Not a valid path
+-- A valid single vertex path
 SELECT * FROM cypher('cypher_create', $$
 	CREATE p=(a)
 	RETURN p
diff --git a/regress/sql/cypher_match.sql b/regress/sql/cypher_match.sql
index accf0ed..1ccc316 100644
--- a/regress/sql/cypher_match.sql
+++ b/regress/sql/cypher_match.sql
@@ -290,7 +290,7 @@ SELECT * FROM cypher('cypher_match', $$MATCH (n:e1)-[]-() RETURN n$$) AS (n agty
 SELECT * FROM cypher('cypher_match', $$MATCH (n:vmissing)-[]-() RETURN n$$) AS (n agtype);
 
 --
---Errors
+-- Path of one vertex. This should select 14
 --
 SELECT * FROM cypher('cypher_match', $$
        MATCH p=() RETURN p
diff --git a/src/backend/parser/cypher_clause.c b/src/backend/parser/cypher_clause.c
index 784b842..c540237 100644
--- a/src/backend/parser/cypher_clause.c
+++ b/src/backend/parser/cypher_clause.c
@@ -3613,13 +3613,12 @@ transform_match_create_path_variable(cypher_parsestate *cpstate,
     List *entity_exprs = NIL;
     ListCell *lc;
 
-    if (list_length(entities) < 3)
+    if (list_length(entities) < 1)
     {
         ereport(ERROR,
                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                 errmsg("paths consist of alternating vertices and edges."),
-                 parser_errposition(pstate, path->location),
-                 errhint("paths require at least 2 vertices and 1 edge")));
+                 errmsg("paths require at least 1 vertex"),
+                 parser_errposition(pstate, path->location)));
     }
 
     // extract the expr for each entity
@@ -4267,13 +4266,12 @@ transform_cypher_create_path(cypher_parsestate *cpstate, List **target_list,
     {
         TargetEntry *te;
 
-        if (list_length(transformed_path) < 3)
+        if (list_length(transformed_path) < 1)
         {
             ereport(ERROR,
                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                     errmsg("paths consist of alternating vertices and edges."),
-                     parser_errposition(pstate, path->location),
-                     errhint("paths require at least 2 vertices and 1 edge")));
+                     errmsg("paths require at least 1 vertex"),
+                     parser_errposition(pstate, path->location)));
         }
 
         te = placeholder_target_entry(cpstate, path->var_name);
diff --git a/src/backend/utils/adt/agtype.c b/src/backend/utils/adt/agtype.c
index f1768aa..e90c908 100644
--- a/src/backend/utils/adt/agtype.c
+++ b/src/backend/utils/adt/agtype.c
@@ -1780,20 +1780,18 @@ Datum _agtype_build_path(PG_FUNCTION_ARGS)
     /* build argument values to build the object */
     nargs = extract_variadic_args(fcinfo, 0, true, &args, &types, &nulls);
 
-    if (nargs < 3)
+    if (nargs < 1)
     {
         ereport(ERROR,
                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                 errmsg("paths consist of alternating vertices and edges"),
-                 errhint("paths require at least 2 vertices and 1 edge")));
+                 errmsg("paths require at least 1 vertex")));
     }
 
     if (nargs % 2 == 0)
     {
         ereport(ERROR,
                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                 errmsg("paths consist of alternating vertices and edges"),
-                 errhint("paths require an odd number of elements")));
+                 errmsg("a path is of the form: [vertex, (edge, vertex)*i] where i >= 0")));
     }
 
     /*
@@ -1935,10 +1933,20 @@ Datum make_path(List *path)
 
     result.res = push_agtype_value(&result.parse_state, WAGT_BEGIN_ARRAY, NULL);
 
-    if (list_length(path) < 3 || list_length(path) % 2 != 1)
+    if (list_length(path) < 1)
+    {
+        ereport(ERROR,
+                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                 errmsg("paths require at least 1 vertex")));
+    }
+
+    if (list_length(path) % 2 != 1)
+    {
         ereport(ERROR,
                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                 errmsg("path list is not a valid path")));
+                 errmsg("a path is of the form: [vertex, (edge, vertex)*i] where i >= 0")));
+    }
+
 
     foreach (lc, path)
     {