This is an automated email from the ASF dual-hosted git repository.
rafsun42 pushed a commit to branch PG12
in repository https://gitbox.apache.org/repos/asf/age.git
The following commit(s) were added to refs/heads/PG12 by this push:
new 5f49a2da Fix issue 395: ERROR: container is not an agtype array
(#1039) (#1150)
5f49a2da is described below
commit 5f49a2da862e56f1b324d9a98f5fe5e0df3fab46
Author: John Gemignani <[email protected]>
AuthorDate: Tue Aug 15 16:21:08 2023 -0700
Fix issue 395: ERROR: container is not an agtype array (#1039) (#1150)
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 6c0266e9..52f5eb02 100644
--- a/regress/expected/expr.out
+++ b/regress/expected/expr.out
@@ -6908,9 +6908,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 d2248497..50128628 100644
--- a/regress/sql/expr.sql
+++ b/regress/sql/expr.sql
@@ -2802,9 +2802,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 736f41d2..359bbd79 100644
--- a/src/backend/utils/adt/agtype.c
+++ b/src/backend/utils/adt/agtype.c
@@ -9752,6 +9752,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);
@@ -9781,23 +9782,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);
}