Skip to content

Commit

Permalink
Fix Issue 1634: Setting all properties with map object causes error (a…
Browse files Browse the repository at this point in the history
…pache#1637)

Fixed the issue where setting the properties would not work, if it where
an object passed as the properties.

Added regression tests.
  • Loading branch information
jrgemignani committed Mar 8, 2024
1 parent 681daeb commit 2983e94
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 5 deletions.
66 changes: 66 additions & 0 deletions regress/expected/cypher_set.out
Original file line number Diff line number Diff line change
Expand Up @@ -935,6 +935,59 @@ $$) AS (p agtype);
{"id": 281474976710658, "label": "", "properties": {"n0": true, "n1": false, "n2": true}}::vertex
(1 row)

--
-- Issue 1634: Setting all properties with map object causes error
--
SELECT * FROM create_graph('issue_1634');
NOTICE: graph "issue_1634" has been created
create_graph
--------------

(1 row)

-- this did not work and was fixed
SELECT * FROM cypher('issue_1634', $$ WITH {first: 'jon', last: 'snow'} AS map
MERGE (v:PERSION {id: '1'})
SET v=map
RETURN v,map $$) as (v agtype, map agtype);
v | map
-----------------------------------------------------------------------------------------------------+----------------------------------
{"id": 844424930131969, "label": "PERSION", "properties": {"last": "snow", "first": "jon"}}::vertex | {"last": "snow", "first": "jon"}
(1 row)

-- these 2 did work and are added as extra tests
SELECT * FROM cypher('issue_1634', $$ MATCH (u) DELETE (u) $$) AS (u agtype);
u
---
(0 rows)

SELECT * FROM cypher('issue_1634', $$ WITH {first: 'jon', last: 'snow'} AS map
MERGE (v:PERSION {id: '1'})
SET v.first=map.first, v.last=map.last
RETURN v,map $$) as (v agtype, map agtype);
v | map
----------------------------------------------------------------------------------------------------------------+----------------------------------
{"id": 844424930131970, "label": "PERSION", "properties": {"id": "1", "last": "snow", "first": "jon"}}::vertex | {"last": "snow", "first": "jon"}
(1 row)

SELECT * FROM cypher('issue_1634', $$ MATCH (u) DELETE (u) $$) AS (u agtype);
u
---
(0 rows)

SELECT * FROM cypher('issue_1634', $$ MERGE (v:PERSION {id: '1'})
SET v={first: 'jon', last: 'snow'}
RETURN v $$) as (v agtype);
v
-----------------------------------------------------------------------------------------------------
{"id": 844424930131971, "label": "PERSION", "properties": {"last": "snow", "first": "jon"}}::vertex
(1 row)

SELECT * FROM cypher('issue_1634', $$ MATCH (u) DELETE (u) $$) AS (u agtype);
u
---
(0 rows)

--
-- Clean up
--
Expand Down Expand Up @@ -974,4 +1027,17 @@ NOTICE: graph "cypher_set_1" has been dropped

(1 row)

SELECT drop_graph('issue_1634', true);
NOTICE: drop cascades to 3 other objects
DETAIL: drop cascades to table issue_1634._ag_label_vertex
drop cascades to table issue_1634._ag_label_edge
drop cascades to table issue_1634."PERSION"
NOTICE: graph "issue_1634" has been dropped
drop_graph
------------

(1 row)

--
-- End
--
29 changes: 28 additions & 1 deletion regress/sql/cypher_set.sql
Original file line number Diff line number Diff line change
Expand Up @@ -354,13 +354,40 @@ SELECT * FROM cypher('cypher_set_1', $$
CREATE (x) SET x.n0 = (true OR false), x.n1 = (false AND false), x.n2 = (false = false) RETURN x
$$) AS (p agtype);

--
-- Issue 1634: Setting all properties with map object causes error
--
SELECT * FROM create_graph('issue_1634');

-- this did not work and was fixed
SELECT * FROM cypher('issue_1634', $$ WITH {first: 'jon', last: 'snow'} AS map
MERGE (v:PERSION {id: '1'})
SET v=map
RETURN v,map $$) as (v agtype, map agtype);

-- these 2 did work and are added as extra tests
SELECT * FROM cypher('issue_1634', $$ MATCH (u) DELETE (u) $$) AS (u agtype);
SELECT * FROM cypher('issue_1634', $$ WITH {first: 'jon', last: 'snow'} AS map
MERGE (v:PERSION {id: '1'})
SET v.first=map.first, v.last=map.last
RETURN v,map $$) as (v agtype, map agtype);

SELECT * FROM cypher('issue_1634', $$ MATCH (u) DELETE (u) $$) AS (u agtype);
SELECT * FROM cypher('issue_1634', $$ MERGE (v:PERSION {id: '1'})
SET v={first: 'jon', last: 'snow'}
RETURN v $$) as (v agtype);

SELECT * FROM cypher('issue_1634', $$ MATCH (u) DELETE (u) $$) AS (u agtype);

--
-- Clean up
--
DROP TABLE tbl;
DROP FUNCTION set_test;
SELECT drop_graph('cypher_set', true);
SELECT drop_graph('cypher_set_1', true);
SELECT drop_graph('issue_1634', true);

--

-- End
--
27 changes: 23 additions & 4 deletions src/backend/utils/adt/agtype.c
Original file line number Diff line number Diff line change
Expand Up @@ -5560,25 +5560,44 @@ Datum age_properties(PG_FUNCTION_ARGS)

/* check for null */
if (PG_ARGISNULL(0))
{
PG_RETURN_NULL();
}

agt_arg = AG_GET_ARG_AGTYPE_P(0);
/* check for a scalar object */
if (!AGT_ROOT_IS_SCALAR(agt_arg))
/* check for a scalar or regular object */

if (!AGT_ROOT_IS_SCALAR(agt_arg) && !AGT_ROOT_IS_OBJECT(agt_arg))
{
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("properties() argument must resolve to a scalar value")));
errmsg("properties() argument must resolve to an object")));
}

/*
* If it isn't an array (wrapped scalar) and is an object, just return it.
* This is necessary for some cases where an object may be passed in. For
* example, SET v={blah}.
*/
if (!AGT_ROOT_IS_ARRAY(agt_arg) && AGT_ROOT_IS_OBJECT(agt_arg))
{
PG_RETURN_POINTER(agt_arg);
}

/* get the object out of the array */
agtv_object = get_ith_agtype_value_from_container(&agt_arg->root, 0);

/* is it an agtype null? */
if (agtv_object->type == AGTV_NULL)
PG_RETURN_NULL();
{
PG_RETURN_NULL();
}

/* check for proper agtype */
if (agtv_object->type != AGTV_VERTEX && agtv_object->type != AGTV_EDGE)
{
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("properties() argument must be a vertex, an edge or null")));
}

agtv_result = GET_AGTYPE_VALUE_OBJECT_VALUE(agtv_object, "properties");

Expand Down

0 comments on commit 2983e94

Please sign in to comment.