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

rafsun42 pushed a commit to branch PG11
in repository https://gitbox.apache.org/repos/asf/age.git


The following commit(s) were added to refs/heads/PG11 by this push:
     new 94f4ddfa Fix issue 395: ERROR: container is not an agtype array 
(#1039) (#1151)
94f4ddfa is described below

commit 94f4ddfaf6ee7582509009008e592c31763efc54
Author: John Gemignani <[email protected]>
AuthorDate: Tue Aug 15 16:22:29 2023 -0700

    Fix issue 395: ERROR: container is not an agtype array (#1039) (#1151)
    
    Fixed issue 395 -
    
    ERROR: container is not an agtype array
    
    This was due to an incorrect order in checking for AGTV_NULL in
    the collect aggregate transfer function: age_collect_aggtransfn
    
    Added regression tests.
---
 regress/expected/expr.out      | 75 ++++++++++++++++++++++++++++++++++++++++++
 regress/sql/expr.sql           | 35 ++++++++++++++++++++
 src/backend/utils/adt/agtype.c | 17 ++++++----
 3 files changed, 120 insertions(+), 7 deletions(-)

diff --git a/regress/expected/expr.out b/regress/expected/expr.out
index c75b6c81..942fc101 100644
--- a/regress/expected/expr.out
+++ b/regress/expected/expr.out
@@ -6907,9 +6907,84 @@ SELECT * FROM cypher('expr', $$MATCH (u) RETURN 
toString(pg_catalog.pg_typeof(u.
  "agtype"
 (7 rows)
 
+-- issue: 395 aggregate function collect() incorrect container for operation
+SELECT create_graph('graph_395');
+NOTICE:  graph "graph_395" has been created
+ create_graph 
+--------------
+ 
+(1 row)
+
+SELECT * FROM cypher('graph_395', $$ CREATE (n:Project {name: 'Project A'}),
+                                            (m:Project {name: 'Project B'}),
+                                            (a:Task {name: 'Task A', size: 
10}),
+                                            (b:Task {name: 'Task B', size: 5}),
+                                            (c:Task {name: 'Task C', size: 7}),
+                                            (x:Person {name: 'John', age: 55}),
+                                            (y:Person {name: 'Bob', age: 43}),
+                                            (z:Person {name: 'Alice', age: 
33}),
+                                            (n)-[:Has]->(a),
+                                            (n)-[:Has]->(b),
+                                            (m)-[:Has]->(c),
+                                            (a)-[:AssignedTo]->(x),
+                                            (b)-[:AssignedTo]->(y),
+                                            (c)-[:AssignedTo]->(y) $$) as (n 
agtype);
+ n 
+---
+(0 rows)
+
+SELECT * FROM cypher('graph_395', $$ MATCH 
(p:Project)-[:Has]->(t:Task)-[:AssignedTo]->(u:Person)
+                                     WITH p, t, collect(u) AS users
+                                     WITH p, {tn: t.name, users: users} AS task
+                                     RETURN task $$) AS (p agtype);
+                                                              p                
                                              
+-----------------------------------------------------------------------------------------------------------------------------
+ {"tn": "Task A", "users": [{"id": 1407374883553281, "label": "Person", 
"properties": {"age": 55, "name": "John"}}::vertex]}
+ {"tn": "Task B", "users": [{"id": 1407374883553282, "label": "Person", 
"properties": {"age": 43, "name": "Bob"}}::vertex]}
+ {"tn": "Task C", "users": [{"id": 1407374883553282, "label": "Person", 
"properties": {"age": 43, "name": "Bob"}}::vertex]}
+(3 rows)
+
+SELECT * FROM cypher('graph_395', $$ MATCH 
(p:Project)-[:Has]->(t:Task)-[:AssignedTo]->(u:Person)
+                                     WITH p, t, collect(u) AS users
+                                     WITH p, {tn: t.name, users: users} AS task
+                                     WITH p, collect(task) AS tasks
+                                     RETURN tasks $$) AS (p agtype);
+                                                                               
                                              p                                 
                                                                                
            
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ [{"tn": "Task A", "users": [{"id": 1407374883553281, "label": "Person", 
"properties": {"age": 55, "name": "John"}}::vertex]}, {"tn": "Task B", "users": 
[{"id": 1407374883553282, "label": "Person", "properties": {"age": 43, "name": 
"Bob"}}::vertex]}]
+ [{"tn": "Task C", "users": [{"id": 1407374883553282, "label": "Person", 
"properties": {"age": 43, "name": "Bob"}}::vertex]}]
+(2 rows)
+
+SELECT * FROM cypher('graph_395', $$ MATCH 
(p:Project)-[:Has]->(t:Task)-[:AssignedTo]->(u:Person)
+                                     WITH p, t, collect(u) AS users
+                                     WITH p, {tn: t.name, users: users} AS task
+                                     WITH p, collect(task) AS tasks
+                                     WITH {pn: p.name, tasks:tasks} AS project
+                                     RETURN project $$) AS (p agtype);
+                                                                               
                                                             p                  
                                                                                
                                          
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ {"pn": "Project A", "tasks": [{"tn": "Task A", "users": [{"id": 
1407374883553281, "label": "Person", "properties": {"age": 55, "name": 
"John"}}::vertex]}, {"tn": "Task B", "users": [{"id": 1407374883553282, 
"label": "Person", "properties": {"age": 43, "name": "Bob"}}::vertex]}]}
+ {"pn": "Project B", "tasks": [{"tn": "Task C", "users": [{"id": 
1407374883553282, "label": "Person", "properties": {"age": 43, "name": 
"Bob"}}::vertex]}]}
+(2 rows)
+
 --
 -- Cleanup
 --
+SELECT * FROM drop_graph('graph_395', true);
+NOTICE:  drop cascades to 7 other objects
+DETAIL:  drop cascades to table graph_395._ag_label_vertex
+drop cascades to table graph_395._ag_label_edge
+drop cascades to table graph_395."Project"
+drop cascades to table graph_395."Task"
+drop cascades to table graph_395."Person"
+drop cascades to table graph_395."Has"
+drop cascades to table graph_395."AssignedTo"
+NOTICE:  graph "graph_395" has been dropped
+ drop_graph 
+------------
+ 
+(1 row)
+
 SELECT * FROM drop_graph('chained', true);
 NOTICE:  drop cascades to 3 other objects
 DETAIL:  drop cascades to table chained._ag_label_vertex
diff --git a/regress/sql/expr.sql b/regress/sql/expr.sql
index b41cc8b3..7cd74fed 100644
--- a/regress/sql/expr.sql
+++ b/regress/sql/expr.sql
@@ -2801,9 +2801,44 @@ SELECT * FROM cypher('list',$$ MATCH p=(n:xyz)-[e]->() 
SET n.array=[0, 1, 2, 3,
 -- pg_typeof
 SELECT * FROM cypher('expr', $$MATCH (u) RETURN 
toString(pg_catalog.pg_typeof(u.id)) $$) AS (u agtype);
 
+-- issue: 395 aggregate function collect() incorrect container for operation
+SELECT create_graph('graph_395');
+SELECT * FROM cypher('graph_395', $$ CREATE (n:Project {name: 'Project A'}),
+                                            (m:Project {name: 'Project B'}),
+                                            (a:Task {name: 'Task A', size: 
10}),
+                                            (b:Task {name: 'Task B', size: 5}),
+                                            (c:Task {name: 'Task C', size: 7}),
+                                            (x:Person {name: 'John', age: 55}),
+                                            (y:Person {name: 'Bob', age: 43}),
+                                            (z:Person {name: 'Alice', age: 
33}),
+                                            (n)-[:Has]->(a),
+                                            (n)-[:Has]->(b),
+                                            (m)-[:Has]->(c),
+                                            (a)-[:AssignedTo]->(x),
+                                            (b)-[:AssignedTo]->(y),
+                                            (c)-[:AssignedTo]->(y) $$) as (n 
agtype);
+
+SELECT * FROM cypher('graph_395', $$ MATCH 
(p:Project)-[:Has]->(t:Task)-[:AssignedTo]->(u:Person)
+                                     WITH p, t, collect(u) AS users
+                                     WITH p, {tn: t.name, users: users} AS task
+                                     RETURN task $$) AS (p agtype);
+
+SELECT * FROM cypher('graph_395', $$ MATCH 
(p:Project)-[:Has]->(t:Task)-[:AssignedTo]->(u:Person)
+                                     WITH p, t, collect(u) AS users
+                                     WITH p, {tn: t.name, users: users} AS task
+                                     WITH p, collect(task) AS tasks
+                                     RETURN tasks $$) AS (p agtype);
+
+SELECT * FROM cypher('graph_395', $$ MATCH 
(p:Project)-[:Has]->(t:Task)-[:AssignedTo]->(u:Person)
+                                     WITH p, t, collect(u) AS users
+                                     WITH p, {tn: t.name, users: users} AS task
+                                     WITH p, collect(task) AS tasks
+                                     WITH {pn: p.name, tasks:tasks} AS project
+                                     RETURN project $$) AS (p agtype);
 --
 -- Cleanup
 --
+SELECT * FROM drop_graph('graph_395', true);
 SELECT * FROM drop_graph('chained', true);
 SELECT * FROM drop_graph('VLE', true);
 SELECT * FROM drop_graph('case_statement', true);
diff --git a/src/backend/utils/adt/agtype.c b/src/backend/utils/adt/agtype.c
index fbcd119c..c4e4a8b0 100644
--- a/src/backend/utils/adt/agtype.c
+++ b/src/backend/utils/adt/agtype.c
@@ -9743,6 +9743,7 @@ Datum age_collect_aggtransfn(PG_FUNCTION_ARGS)
         /* create and initialize the state */
         castate = palloc0(sizeof(agtype_in_state));
         memset(castate, 0, sizeof(agtype_in_state));
+
         /* start the array */
         castate->res = push_agtype_value(&castate->parse_state,
                                          WAGT_BEGIN_ARRAY, NULL);
@@ -9772,23 +9773,25 @@ Datum age_collect_aggtransfn(PG_FUNCTION_ARGS)
         /* only add non null values */
         if (nulls[0] == false)
         {
+            agtype_value *agtv_value = NULL;
+
             /* we need to check for agtype null and skip it, if found */
             if (types[0] == AGTYPEOID)
             {
                 agtype *agt_arg;
-                agtype_value *agtv_value;
 
                 /* get the agtype argument */
                 agt_arg = DATUM_GET_AGTYPE_P(args[0]);
-                agtv_value = 
get_ith_agtype_value_from_container(&agt_arg->root,
-                                                                 0);
-                /* add the arg if not agtype null */
-                if (agtv_value->type != AGTV_NULL)
+
+                /* get the scalar value */
+                if (AGTYPE_CONTAINER_IS_SCALAR(&agt_arg->root))
                 {
-                    add_agtype(args[0], nulls[0], castate, types[0], false);
+                    agtv_value = 
get_ith_agtype_value_from_container(&agt_arg->root, 0);
                 }
             }
-            else
+
+            /* skip the arg if agtype null */
+            if (agtv_value == NULL || agtv_value->type != AGTV_NULL)
             {
                 add_agtype(args[0], nulls[0], castate, types[0], false);
             }

Reply via email to