You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@age.apache.org by jo...@apache.org on 2022/04/21 17:14:47 UTC

[incubator-age] branch master updated: Allow lists and maps to be used in the SET clause

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

joshinnis 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 ab70781  Allow lists and maps to be used in the SET clause
ab70781 is described below

commit ab70781b4b311922f14f2bcb1b2144f1df9a9da1
Author: Josh Innis <Jo...@gmail.com>
AuthorDate: Thu Apr 21 10:13:28 2022 -0700

    Allow lists and maps to be used in the SET clause
    
    Patch fixes a bug that did not allow lists or maps
    to be used in the SET clause properly.
    
    Optimized some code in the SET clause.
    
    Code cleanup and documenation added too.
---
 regress/expected/cypher_set.out   | 176 +++++++++++++++++++++++++++++++++++++-
 regress/sql/cypher_set.sql        |  33 ++++++-
 src/backend/executor/cypher_set.c |  75 +++++++++++++++-
 src/backend/utils/adt/agtype.c    | 113 +++++++++++++++++++++---
 4 files changed, 380 insertions(+), 17 deletions(-)

diff --git a/regress/expected/cypher_set.out b/regress/expected/cypher_set.out
index 45e9ff7..5cd42ee 100644
--- a/regress/expected/cypher_set.out
+++ b/regress/expected/cypher_set.out
@@ -493,6 +493,180 @@ SELECT * FROM cypher('cypher_set', $$MATCH (u:begin)-[:edge]->(v:end) return u,
  {"id": 1970324836974593, "label": "begin", "properties": {"i": 2, "j": 4}}::vertex | {"id": 2533274790395905, "label": "end", "properties": {"i": 1, "j": 3}}::vertex
 (1 row)
 
+-- test lists
+SELECT * FROM cypher('cypher_set', $$MATCH (n) SET n.i = [3, 'test', [1, 2, 3], {id: 1}, 1.0, 1.0::numeric] RETURN n$$) AS (a agtype);
+                                                                                 a                                                                                  
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ {"id": 281474976710659, "label": "", "properties": {"i": [3, "test", [1, 2, 3], {"id": 1}, 1.0, 1::numeric], "j": 5, "y": 2}}::vertex
+ {"id": 281474976710658, "label": "", "properties": {"i": [3, "test", [1, 2, 3], {"id": 1}, 1.0, 1::numeric], "j": 5, "t": 150, "y": 1}}::vertex
+ {"id": 281474976710657, "label": "", "properties": {"i": [3, "test", [1, 2, 3], {"id": 1}, 1.0, 1::numeric], "j": 5, "t": 150}}::vertex
+ {"id": 844424930131970, "label": "v", "properties": {"a": 0, "i": [3, "test", [1, 2, 3], {"id": 1}, 1.0, 1::numeric], "j": 5, "t": 150, "y": 99, "z": 99}}::vertex
+ {"id": 844424930131969, "label": "v", "properties": {"i": [3, "test", [1, 2, 3], {"id": 1}, 1.0, 1::numeric], "j": 5, "t": 150}}::vertex
+ {"id": 844424930131971, "label": "v", "properties": {"i": [3, "test", [1, 2, 3], {"id": 1}, 1.0, 1::numeric], "j": 5, "t": 150}}::vertex
+ {"id": 1407374883553281, "label": "other_v", "properties": {"i": [3, "test", [1, 2, 3], {"id": 1}, 1.0, 1::numeric], "j": 5, "k": 10}}::vertex
+ {"id": 1407374883553282, "label": "other_v", "properties": {"i": [3, "test", [1, 2, 3], {"id": 1}, 1.0, 1::numeric], "j": 5, "k": 10}}::vertex
+ {"id": 1407374883553283, "label": "other_v", "properties": {"i": [3, "test", [1, 2, 3], {"id": 1}, 1.0, 1::numeric], "j": 5, "k": 10}}::vertex
+ {"id": 1407374883553284, "label": "other_v", "properties": {"i": [3, "test", [1, 2, 3], {"id": 1}, 1.0, 1::numeric], "j": 5, "k": 10}}::vertex
+ {"id": 1688849860263937, "label": "vertices", "properties": {"i": [3, "test", [1, 2, 3], {"id": 1}, 1.0, 1::numeric], "j": 6, "k": 9}}::vertex
+ {"id": 1970324836974593, "label": "begin", "properties": {"i": [3, "test", [1, 2, 3], {"id": 1}, 1.0, 1::numeric], "j": 4}}::vertex
+ {"id": 2533274790395905, "label": "end", "properties": {"i": [3, "test", [1, 2, 3], {"id": 1}, 1.0, 1::numeric], "j": 3}}::vertex
+(13 rows)
+
+SELECT * FROM cypher('cypher_set', $$MATCH (n) RETURN n$$) AS (a agtype);
+                                                                                 a                                                                                  
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ {"id": 281474976710659, "label": "", "properties": {"i": [3, "test", [1, 2, 3], {"id": 1}, 1.0, 1::numeric], "j": 5, "y": 2}}::vertex
+ {"id": 281474976710658, "label": "", "properties": {"i": [3, "test", [1, 2, 3], {"id": 1}, 1.0, 1::numeric], "j": 5, "t": 150, "y": 1}}::vertex
+ {"id": 281474976710657, "label": "", "properties": {"i": [3, "test", [1, 2, 3], {"id": 1}, 1.0, 1::numeric], "j": 5, "t": 150}}::vertex
+ {"id": 844424930131970, "label": "v", "properties": {"a": 0, "i": [3, "test", [1, 2, 3], {"id": 1}, 1.0, 1::numeric], "j": 5, "t": 150, "y": 99, "z": 99}}::vertex
+ {"id": 844424930131969, "label": "v", "properties": {"i": [3, "test", [1, 2, 3], {"id": 1}, 1.0, 1::numeric], "j": 5, "t": 150}}::vertex
+ {"id": 844424930131971, "label": "v", "properties": {"i": [3, "test", [1, 2, 3], {"id": 1}, 1.0, 1::numeric], "j": 5, "t": 150}}::vertex
+ {"id": 1407374883553281, "label": "other_v", "properties": {"i": [3, "test", [1, 2, 3], {"id": 1}, 1.0, 1::numeric], "j": 5, "k": 10}}::vertex
+ {"id": 1407374883553282, "label": "other_v", "properties": {"i": [3, "test", [1, 2, 3], {"id": 1}, 1.0, 1::numeric], "j": 5, "k": 10}}::vertex
+ {"id": 1407374883553283, "label": "other_v", "properties": {"i": [3, "test", [1, 2, 3], {"id": 1}, 1.0, 1::numeric], "j": 5, "k": 10}}::vertex
+ {"id": 1407374883553284, "label": "other_v", "properties": {"i": [3, "test", [1, 2, 3], {"id": 1}, 1.0, 1::numeric], "j": 5, "k": 10}}::vertex
+ {"id": 1688849860263937, "label": "vertices", "properties": {"i": [3, "test", [1, 2, 3], {"id": 1}, 1.0, 1::numeric], "j": 6, "k": 9}}::vertex
+ {"id": 1970324836974593, "label": "begin", "properties": {"i": [3, "test", [1, 2, 3], {"id": 1}, 1.0, 1::numeric], "j": 4}}::vertex
+ {"id": 2533274790395905, "label": "end", "properties": {"i": [3, "test", [1, 2, 3], {"id": 1}, 1.0, 1::numeric], "j": 3}}::vertex
+(13 rows)
+
+-- test that lists get updated in paths
+SELECT * FROM cypher('cypher_set', $$MATCH p=(u:begin)-[:edge]->(v:end) SET u.i = [1, 2, 3] return u, p $$) AS (u agtype, p agtype);
+                                             u                                              |                                                                                                                                                                                 p                                                                                                                                                                                  
+--------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ {"id": 1970324836974593, "label": "begin", "properties": {"i": [1, 2, 3], "j": 4}}::vertex | [{"id": 1970324836974593, "label": "begin", "properties": {"i": [1, 2, 3], "j": 4}}::vertex, {"id": 2251799813685249, "label": "edge", "end_id": 2533274790395905, "start_id": 1970324836974593, "properties": {}}::edge, {"id": 2533274790395905, "label": "end", "properties": {"i": [3, "test", [1, 2, 3], {"id": 1}, 1.0, 1::numeric], "j": 3}}::vertex]::path
+(1 row)
+
+SELECT * FROM cypher('cypher_set', $$MATCH p=(u:begin)-[:edge]->(v:end) return u, p $$) AS (u agtype, p agtype);
+                                             u                                              |                                                                                                                                                                                 p                                                                                                                                                                                  
+--------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ {"id": 1970324836974593, "label": "begin", "properties": {"i": [1, 2, 3], "j": 4}}::vertex | [{"id": 1970324836974593, "label": "begin", "properties": {"i": [1, 2, 3], "j": 4}}::vertex, {"id": 2251799813685249, "label": "edge", "end_id": 2533274790395905, "start_id": 1970324836974593, "properties": {}}::edge, {"id": 2533274790395905, "label": "end", "properties": {"i": [3, "test", [1, 2, 3], {"id": 1}, 1.0, 1::numeric], "j": 3}}::vertex]::path
+(1 row)
+
+-- test empty lists
+SELECT * FROM cypher('cypher_set', $$MATCH (n) SET n.i = [] RETURN n$$) AS (a agtype);
+                                                         a                                                          
+--------------------------------------------------------------------------------------------------------------------
+ {"id": 281474976710659, "label": "", "properties": {"i": [], "j": 5, "y": 2}}::vertex
+ {"id": 281474976710658, "label": "", "properties": {"i": [], "j": 5, "t": 150, "y": 1}}::vertex
+ {"id": 281474976710657, "label": "", "properties": {"i": [], "j": 5, "t": 150}}::vertex
+ {"id": 844424930131970, "label": "v", "properties": {"a": 0, "i": [], "j": 5, "t": 150, "y": 99, "z": 99}}::vertex
+ {"id": 844424930131969, "label": "v", "properties": {"i": [], "j": 5, "t": 150}}::vertex
+ {"id": 844424930131971, "label": "v", "properties": {"i": [], "j": 5, "t": 150}}::vertex
+ {"id": 1407374883553281, "label": "other_v", "properties": {"i": [], "j": 5, "k": 10}}::vertex
+ {"id": 1407374883553282, "label": "other_v", "properties": {"i": [], "j": 5, "k": 10}}::vertex
+ {"id": 1407374883553283, "label": "other_v", "properties": {"i": [], "j": 5, "k": 10}}::vertex
+ {"id": 1407374883553284, "label": "other_v", "properties": {"i": [], "j": 5, "k": 10}}::vertex
+ {"id": 1688849860263937, "label": "vertices", "properties": {"i": [], "j": 6, "k": 9}}::vertex
+ {"id": 1970324836974593, "label": "begin", "properties": {"i": [], "j": 4}}::vertex
+ {"id": 2533274790395905, "label": "end", "properties": {"i": [], "j": 3}}::vertex
+(13 rows)
+
+SELECT * FROM cypher('cypher_set', $$MATCH (n) RETURN n$$) AS (a agtype);
+                                                         a                                                          
+--------------------------------------------------------------------------------------------------------------------
+ {"id": 281474976710659, "label": "", "properties": {"i": [], "j": 5, "y": 2}}::vertex
+ {"id": 281474976710658, "label": "", "properties": {"i": [], "j": 5, "t": 150, "y": 1}}::vertex
+ {"id": 281474976710657, "label": "", "properties": {"i": [], "j": 5, "t": 150}}::vertex
+ {"id": 844424930131970, "label": "v", "properties": {"a": 0, "i": [], "j": 5, "t": 150, "y": 99, "z": 99}}::vertex
+ {"id": 844424930131969, "label": "v", "properties": {"i": [], "j": 5, "t": 150}}::vertex
+ {"id": 844424930131971, "label": "v", "properties": {"i": [], "j": 5, "t": 150}}::vertex
+ {"id": 1407374883553281, "label": "other_v", "properties": {"i": [], "j": 5, "k": 10}}::vertex
+ {"id": 1407374883553282, "label": "other_v", "properties": {"i": [], "j": 5, "k": 10}}::vertex
+ {"id": 1407374883553283, "label": "other_v", "properties": {"i": [], "j": 5, "k": 10}}::vertex
+ {"id": 1407374883553284, "label": "other_v", "properties": {"i": [], "j": 5, "k": 10}}::vertex
+ {"id": 1688849860263937, "label": "vertices", "properties": {"i": [], "j": 6, "k": 9}}::vertex
+ {"id": 1970324836974593, "label": "begin", "properties": {"i": [], "j": 4}}::vertex
+ {"id": 2533274790395905, "label": "end", "properties": {"i": [], "j": 3}}::vertex
+(13 rows)
+
+-- test maps
+SELECT * FROM cypher('cypher_set', $$MATCH (n) SET n.i = {prop1: 3, prop2:'test', prop3: [1, 2, 3], prop4: {id: 1}, prop5: 1.0, prop6:1.0::numeric} RETURN n$$) AS (a agtype);
+                                                                                                            a                                                                                                             
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ {"id": 281474976710659, "label": "", "properties": {"i": {"prop1": 3, "prop2": "test", "prop3": [1, 2, 3], "prop4": {"id": 1}, "prop5": 1.0, "prop6": 1::numeric}, "j": 5, "y": 2}}::vertex
+ {"id": 281474976710658, "label": "", "properties": {"i": {"prop1": 3, "prop2": "test", "prop3": [1, 2, 3], "prop4": {"id": 1}, "prop5": 1.0, "prop6": 1::numeric}, "j": 5, "t": 150, "y": 1}}::vertex
+ {"id": 281474976710657, "label": "", "properties": {"i": {"prop1": 3, "prop2": "test", "prop3": [1, 2, 3], "prop4": {"id": 1}, "prop5": 1.0, "prop6": 1::numeric}, "j": 5, "t": 150}}::vertex
+ {"id": 844424930131970, "label": "v", "properties": {"a": 0, "i": {"prop1": 3, "prop2": "test", "prop3": [1, 2, 3], "prop4": {"id": 1}, "prop5": 1.0, "prop6": 1::numeric}, "j": 5, "t": 150, "y": 99, "z": 99}}::vertex
+ {"id": 844424930131969, "label": "v", "properties": {"i": {"prop1": 3, "prop2": "test", "prop3": [1, 2, 3], "prop4": {"id": 1}, "prop5": 1.0, "prop6": 1::numeric}, "j": 5, "t": 150}}::vertex
+ {"id": 844424930131971, "label": "v", "properties": {"i": {"prop1": 3, "prop2": "test", "prop3": [1, 2, 3], "prop4": {"id": 1}, "prop5": 1.0, "prop6": 1::numeric}, "j": 5, "t": 150}}::vertex
+ {"id": 1407374883553281, "label": "other_v", "properties": {"i": {"prop1": 3, "prop2": "test", "prop3": [1, 2, 3], "prop4": {"id": 1}, "prop5": 1.0, "prop6": 1::numeric}, "j": 5, "k": 10}}::vertex
+ {"id": 1407374883553282, "label": "other_v", "properties": {"i": {"prop1": 3, "prop2": "test", "prop3": [1, 2, 3], "prop4": {"id": 1}, "prop5": 1.0, "prop6": 1::numeric}, "j": 5, "k": 10}}::vertex
+ {"id": 1407374883553283, "label": "other_v", "properties": {"i": {"prop1": 3, "prop2": "test", "prop3": [1, 2, 3], "prop4": {"id": 1}, "prop5": 1.0, "prop6": 1::numeric}, "j": 5, "k": 10}}::vertex
+ {"id": 1407374883553284, "label": "other_v", "properties": {"i": {"prop1": 3, "prop2": "test", "prop3": [1, 2, 3], "prop4": {"id": 1}, "prop5": 1.0, "prop6": 1::numeric}, "j": 5, "k": 10}}::vertex
+ {"id": 1688849860263937, "label": "vertices", "properties": {"i": {"prop1": 3, "prop2": "test", "prop3": [1, 2, 3], "prop4": {"id": 1}, "prop5": 1.0, "prop6": 1::numeric}, "j": 6, "k": 9}}::vertex
+ {"id": 1970324836974593, "label": "begin", "properties": {"i": {"prop1": 3, "prop2": "test", "prop3": [1, 2, 3], "prop4": {"id": 1}, "prop5": 1.0, "prop6": 1::numeric}, "j": 4}}::vertex
+ {"id": 2533274790395905, "label": "end", "properties": {"i": {"prop1": 3, "prop2": "test", "prop3": [1, 2, 3], "prop4": {"id": 1}, "prop5": 1.0, "prop6": 1::numeric}, "j": 3}}::vertex
+(13 rows)
+
+SELECT * FROM cypher('cypher_set', $$MATCH (n) RETURN n$$) AS (a agtype);
+                                                                                                            a                                                                                                             
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ {"id": 281474976710659, "label": "", "properties": {"i": {"prop1": 3, "prop2": "test", "prop3": [1, 2, 3], "prop4": {"id": 1}, "prop5": 1.0, "prop6": 1::numeric}, "j": 5, "y": 2}}::vertex
+ {"id": 281474976710658, "label": "", "properties": {"i": {"prop1": 3, "prop2": "test", "prop3": [1, 2, 3], "prop4": {"id": 1}, "prop5": 1.0, "prop6": 1::numeric}, "j": 5, "t": 150, "y": 1}}::vertex
+ {"id": 281474976710657, "label": "", "properties": {"i": {"prop1": 3, "prop2": "test", "prop3": [1, 2, 3], "prop4": {"id": 1}, "prop5": 1.0, "prop6": 1::numeric}, "j": 5, "t": 150}}::vertex
+ {"id": 844424930131970, "label": "v", "properties": {"a": 0, "i": {"prop1": 3, "prop2": "test", "prop3": [1, 2, 3], "prop4": {"id": 1}, "prop5": 1.0, "prop6": 1::numeric}, "j": 5, "t": 150, "y": 99, "z": 99}}::vertex
+ {"id": 844424930131969, "label": "v", "properties": {"i": {"prop1": 3, "prop2": "test", "prop3": [1, 2, 3], "prop4": {"id": 1}, "prop5": 1.0, "prop6": 1::numeric}, "j": 5, "t": 150}}::vertex
+ {"id": 844424930131971, "label": "v", "properties": {"i": {"prop1": 3, "prop2": "test", "prop3": [1, 2, 3], "prop4": {"id": 1}, "prop5": 1.0, "prop6": 1::numeric}, "j": 5, "t": 150}}::vertex
+ {"id": 1407374883553281, "label": "other_v", "properties": {"i": {"prop1": 3, "prop2": "test", "prop3": [1, 2, 3], "prop4": {"id": 1}, "prop5": 1.0, "prop6": 1::numeric}, "j": 5, "k": 10}}::vertex
+ {"id": 1407374883553282, "label": "other_v", "properties": {"i": {"prop1": 3, "prop2": "test", "prop3": [1, 2, 3], "prop4": {"id": 1}, "prop5": 1.0, "prop6": 1::numeric}, "j": 5, "k": 10}}::vertex
+ {"id": 1407374883553283, "label": "other_v", "properties": {"i": {"prop1": 3, "prop2": "test", "prop3": [1, 2, 3], "prop4": {"id": 1}, "prop5": 1.0, "prop6": 1::numeric}, "j": 5, "k": 10}}::vertex
+ {"id": 1407374883553284, "label": "other_v", "properties": {"i": {"prop1": 3, "prop2": "test", "prop3": [1, 2, 3], "prop4": {"id": 1}, "prop5": 1.0, "prop6": 1::numeric}, "j": 5, "k": 10}}::vertex
+ {"id": 1688849860263937, "label": "vertices", "properties": {"i": {"prop1": 3, "prop2": "test", "prop3": [1, 2, 3], "prop4": {"id": 1}, "prop5": 1.0, "prop6": 1::numeric}, "j": 6, "k": 9}}::vertex
+ {"id": 1970324836974593, "label": "begin", "properties": {"i": {"prop1": 3, "prop2": "test", "prop3": [1, 2, 3], "prop4": {"id": 1}, "prop5": 1.0, "prop6": 1::numeric}, "j": 4}}::vertex
+ {"id": 2533274790395905, "label": "end", "properties": {"i": {"prop1": 3, "prop2": "test", "prop3": [1, 2, 3], "prop4": {"id": 1}, "prop5": 1.0, "prop6": 1::numeric}, "j": 3}}::vertex
+(13 rows)
+
+-- test maps in paths
+SELECT * FROM cypher('cypher_set', $$MATCH p=(u:begin)-[:edge]->(v:end) SET u.i = {prop1: 1, prop2: 2, prop3: 3} return u, p $$) AS (u agtype, p agtype);
+                                                           u                                                           |                                                                                                                                                                                                                          p                                                                                                                                                          [...]
+-----------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ [...]
+ {"id": 1970324836974593, "label": "begin", "properties": {"i": {"prop1": 1, "prop2": 2, "prop3": 3}, "j": 4}}::vertex | [{"id": 1970324836974593, "label": "begin", "properties": {"i": {"prop1": 1, "prop2": 2, "prop3": 3}, "j": 4}}::vertex, {"id": 2251799813685249, "label": "edge", "end_id": 2533274790395905, "start_id": 1970324836974593, "properties": {}}::edge, {"id": 2533274790395905, "label": "end", "properties": {"i": {"prop1": 3, "prop2": "test", "prop3": [1, 2, 3], "prop4": {"id": [...]
+(1 row)
+
+SELECT * FROM cypher('cypher_set', $$MATCH p=(u:begin)-[:edge]->(v:end) return u, p $$) AS (u agtype, p agtype);
+                                                           u                                                           |                                                                                                                                                                                                                          p                                                                                                                                                          [...]
+-----------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ [...]
+ {"id": 1970324836974593, "label": "begin", "properties": {"i": {"prop1": 1, "prop2": 2, "prop3": 3}, "j": 4}}::vertex | [{"id": 1970324836974593, "label": "begin", "properties": {"i": {"prop1": 1, "prop2": 2, "prop3": 3}, "j": 4}}::vertex, {"id": 2251799813685249, "label": "edge", "end_id": 2533274790395905, "start_id": 1970324836974593, "properties": {}}::edge, {"id": 2533274790395905, "label": "end", "properties": {"i": {"prop1": 3, "prop2": "test", "prop3": [1, 2, 3], "prop4": {"id": [...]
+(1 row)
+
+-- test empty maps
+SELECT * FROM cypher('cypher_set', $$MATCH (n) SET n.i = {} RETURN n$$) AS (a agtype);
+                                                         a                                                          
+--------------------------------------------------------------------------------------------------------------------
+ {"id": 281474976710659, "label": "", "properties": {"i": {}, "j": 5, "y": 2}}::vertex
+ {"id": 281474976710658, "label": "", "properties": {"i": {}, "j": 5, "t": 150, "y": 1}}::vertex
+ {"id": 281474976710657, "label": "", "properties": {"i": {}, "j": 5, "t": 150}}::vertex
+ {"id": 844424930131970, "label": "v", "properties": {"a": 0, "i": {}, "j": 5, "t": 150, "y": 99, "z": 99}}::vertex
+ {"id": 844424930131969, "label": "v", "properties": {"i": {}, "j": 5, "t": 150}}::vertex
+ {"id": 844424930131971, "label": "v", "properties": {"i": {}, "j": 5, "t": 150}}::vertex
+ {"id": 1407374883553281, "label": "other_v", "properties": {"i": {}, "j": 5, "k": 10}}::vertex
+ {"id": 1407374883553282, "label": "other_v", "properties": {"i": {}, "j": 5, "k": 10}}::vertex
+ {"id": 1407374883553283, "label": "other_v", "properties": {"i": {}, "j": 5, "k": 10}}::vertex
+ {"id": 1407374883553284, "label": "other_v", "properties": {"i": {}, "j": 5, "k": 10}}::vertex
+ {"id": 1688849860263937, "label": "vertices", "properties": {"i": {}, "j": 6, "k": 9}}::vertex
+ {"id": 1970324836974593, "label": "begin", "properties": {"i": {}, "j": 4}}::vertex
+ {"id": 2533274790395905, "label": "end", "properties": {"i": {}, "j": 3}}::vertex
+(13 rows)
+
+SELECT * FROM cypher('cypher_set', $$MATCH (n) RETURN n$$) AS (a agtype);
+                                                         a                                                          
+--------------------------------------------------------------------------------------------------------------------
+ {"id": 281474976710659, "label": "", "properties": {"i": {}, "j": 5, "y": 2}}::vertex
+ {"id": 281474976710658, "label": "", "properties": {"i": {}, "j": 5, "t": 150, "y": 1}}::vertex
+ {"id": 281474976710657, "label": "", "properties": {"i": {}, "j": 5, "t": 150}}::vertex
+ {"id": 844424930131970, "label": "v", "properties": {"a": 0, "i": {}, "j": 5, "t": 150, "y": 99, "z": 99}}::vertex
+ {"id": 844424930131969, "label": "v", "properties": {"i": {}, "j": 5, "t": 150}}::vertex
+ {"id": 844424930131971, "label": "v", "properties": {"i": {}, "j": 5, "t": 150}}::vertex
+ {"id": 1407374883553281, "label": "other_v", "properties": {"i": {}, "j": 5, "k": 10}}::vertex
+ {"id": 1407374883553282, "label": "other_v", "properties": {"i": {}, "j": 5, "k": 10}}::vertex
+ {"id": 1407374883553283, "label": "other_v", "properties": {"i": {}, "j": 5, "k": 10}}::vertex
+ {"id": 1407374883553284, "label": "other_v", "properties": {"i": {}, "j": 5, "k": 10}}::vertex
+ {"id": 1688849860263937, "label": "vertices", "properties": {"i": {}, "j": 6, "k": 9}}::vertex
+ {"id": 1970324836974593, "label": "begin", "properties": {"i": {}, "j": 4}}::vertex
+ {"id": 2533274790395905, "label": "end", "properties": {"i": {}, "j": 3}}::vertex
+(13 rows)
+
 --
 -- Clean up
 --
@@ -516,5 +690,3 @@ NOTICE:  graph "cypher_set" has been dropped
 (1 row)
 
 --
--- End
---
diff --git a/regress/sql/cypher_set.sql b/regress/sql/cypher_set.sql
index f3b762f..76a3a02 100644
--- a/regress/sql/cypher_set.sql
+++ b/regress/sql/cypher_set.sql
@@ -174,6 +174,36 @@ END;
 SELECT * FROM cypher('cypher_set', $$MATCH (u:vertices) return u $$) AS (result agtype);
 SELECT * FROM cypher('cypher_set', $$MATCH (u:begin)-[:edge]->(v:end) return u, v $$) AS (u agtype, v agtype);
 
+-- test lists
+SELECT * FROM cypher('cypher_set', $$MATCH (n) SET n.i = [3, 'test', [1, 2, 3], {id: 1}, 1.0, 1.0::numeric] RETURN n$$) AS (a agtype);
+
+SELECT * FROM cypher('cypher_set', $$MATCH (n) RETURN n$$) AS (a agtype);
+
+-- test that lists get updated in paths
+SELECT * FROM cypher('cypher_set', $$MATCH p=(u:begin)-[:edge]->(v:end) SET u.i = [1, 2, 3] return u, p $$) AS (u agtype, p agtype);
+
+SELECT * FROM cypher('cypher_set', $$MATCH p=(u:begin)-[:edge]->(v:end) return u, p $$) AS (u agtype, p agtype);
+
+-- test empty lists
+SELECT * FROM cypher('cypher_set', $$MATCH (n) SET n.i = [] RETURN n$$) AS (a agtype);
+
+SELECT * FROM cypher('cypher_set', $$MATCH (n) RETURN n$$) AS (a agtype);
+
+-- test maps
+SELECT * FROM cypher('cypher_set', $$MATCH (n) SET n.i = {prop1: 3, prop2:'test', prop3: [1, 2, 3], prop4: {id: 1}, prop5: 1.0, prop6:1.0::numeric} RETURN n$$) AS (a agtype);
+
+SELECT * FROM cypher('cypher_set', $$MATCH (n) RETURN n$$) AS (a agtype);
+
+-- test maps in paths
+SELECT * FROM cypher('cypher_set', $$MATCH p=(u:begin)-[:edge]->(v:end) SET u.i = {prop1: 1, prop2: 2, prop3: 3} return u, p $$) AS (u agtype, p agtype);
+
+SELECT * FROM cypher('cypher_set', $$MATCH p=(u:begin)-[:edge]->(v:end) return u, p $$) AS (u agtype, p agtype);
+
+-- test empty maps
+SELECT * FROM cypher('cypher_set', $$MATCH (n) SET n.i = {} RETURN n$$) AS (a agtype);
+
+SELECT * FROM cypher('cypher_set', $$MATCH (n) RETURN n$$) AS (a agtype);
+
 --
 -- Clean up
 --
@@ -182,5 +212,4 @@ DROP FUNCTION set_test;
 SELECT drop_graph('cypher_set', true);
 
 --
--- End
---
+
diff --git a/src/backend/executor/cypher_set.c b/src/backend/executor/cypher_set.c
index c9fba79..9b37b3b 100644
--- a/src/backend/executor/cypher_set.c
+++ b/src/backend/executor/cypher_set.c
@@ -99,7 +99,9 @@ static void begin_cypher_set(CustomScanState *node, EState *estate,
      * that have modified the command id.
      */
     if (estate->es_output_cid == 0)
+    {
         estate->es_output_cid = estate->es_snapshot->curcid;
+    }
 
     Increment_Estate_CommandId(estate);
 }
@@ -133,7 +135,9 @@ static HeapTuple update_entity_tuple(ResultRelInfo *resultRelInfo,
         // Check the constraints of the tuple
         tuple->t_tableOid = RelationGetRelid(resultRelInfo->ri_RelationDesc);
         if (resultRelInfo->ri_RelationDesc->rd_att->constr != NULL)
+        {
             ExecConstraints(resultRelInfo, elemTupleSlot, estate);
+        }
 
         // Insert the tuple normally
         update_result = heap_update(resultRelInfo->ri_RelationDesc,
@@ -143,14 +147,18 @@ static HeapTuple update_entity_tuple(ResultRelInfo *resultRelInfo,
                                     &lockmode);
 
         if (update_result != HeapTupleMayBeUpdated)
-        ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR),
-                        errmsg("Entity failed to be updated: %i",
-                               update_result)));
+        {
+            ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR),
+                            errmsg("Entity failed to be updated: %i",
+                                   update_result)));
+        }
 
         // Insert index entries for the tuple
         if (resultRelInfo->ri_NumIndices > 0)
+        {
             ExecInsertIndexTuples(elemTupleSlot, &(tuple->t_self), estate,
                                   false, NULL, NIL);
+        }
     }
 
     ReleaseBuffer(buffer);
@@ -179,6 +187,11 @@ static void process_all_tuples(CustomScanState *node)
     } while (!TupIsNull(slot));
 }
 
+/*
+ * Checks the path to see if the entities contained within
+ * have the same graphid and the updated_id field. Returns
+ * true if yes, false otherwise.
+ */
 static bool check_path(agtype_value *path, graphid updated_id)
 {
     int i;
@@ -190,12 +203,18 @@ static bool check_path(agtype_value *path, graphid updated_id)
         agtype_value *id = GET_AGTYPE_VALUE_OBJECT_VALUE(elem, "id");
 
         if (updated_id == id->val.int_value)
+        {
             return true;
+        }
     }
 
     return false;
 }
 
+/*
+ * Construct a new agtype path with the entity with updated_id
+ * replacing all of its intances in path with updated_entity
+ */
 static agtype_value *replace_entity_in_path(agtype_value *path,
                                             graphid updated_id,
                                             agtype *updated_entity)
@@ -217,24 +236,37 @@ static agtype_value *replace_entity_in_path(agtype_value *path,
     parsed_agtype_value = push_agtype_value(&parse_state, tok,
                                             tok < WAGT_BEGIN_ARRAY ? r : NULL);
 
+    // Iterate through the path, replace entities as necessary.
     for (i = 0; i < path->val.array.num_elems; i++)
     {
         agtype_value *id, *elem;
 
         elem = &path->val.array.elems[i];
 
+        // something unexpected happended, throw an error.
         if (elem->type != AGTV_VERTEX && elem->type != AGTV_EDGE)
+        {
             ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                             errmsg("unsupported agtype found in a path")));
+        }
 
+        // extract the id field
         id = GET_AGTYPE_VALUE_OBJECT_VALUE(elem, "id");
 
+        /*
+         * Either replace or keep the entity in the new path, depending on the id
+         * check.
+         */
         if (updated_id == id->val.int_value)
+        {
             parsed_agtype_value = push_agtype_value(&parse_state, WAGT_ELEM,
                 get_ith_agtype_value_from_container(&updated_entity->root, 0));
+        }
         else
+        {
             parsed_agtype_value = push_agtype_value(&parse_state, WAGT_ELEM,
                                                     elem);
+        }
     }
 
     parsed_agtype_value = push_agtype_value(&parse_state, WAGT_END_ARRAY, NULL);
@@ -243,6 +275,11 @@ static agtype_value *replace_entity_in_path(agtype_value *path,
     return parsed_agtype_value;
 }
 
+/*
+ * When a vertex or edge is updated, we need to update the vertex
+ * or edge if it is contained within a path. Scan through scanTupleSlot
+ * to find all paths and check if they need to be updated.
+ */
 static void update_all_paths(CustomScanState *node, graphid id,
                              agtype *updated_entity)
 {
@@ -256,19 +293,35 @@ static void update_all_paths(CustomScanState *node, graphid id,
         agtype *original_entity;
         agtype_value *original_entity_value;
 
+        // skip non agtype values
         if (scanTupleSlot->tts_tupleDescriptor->attrs[i].atttypid != AGTYPEOID)
+        {
             continue;
+        }
 
+        // skip nulls
         if (scanTupleSlot->tts_isnull[i])
+        {
             continue;
+        }
 
         original_entity = DATUM_GET_AGTYPE_P(scanTupleSlot->tts_values[i]);
+
+        // if the value is not a scalar type, its not a path
+        if (!AGTYPE_CONTAINER_IS_SCALAR(&original_entity->root))
+        {
+            continue;
+        }
+
         original_entity_value = get_ith_agtype_value_from_container(&original_entity->root, 0);
 
+        // we found a path
         if (original_entity_value->type == AGTV_PATH)
         {
+            // check if the path contains the entity.
             if (check_path(original_entity_value, id))
             {
+                // the path does contain the entity replace with the new entity.
                 agtype_value *new_path = replace_entity_in_path(original_entity_value, id, updated_entity);
 
                 scanTupleSlot->tts_values[i] = AGTYPE_P_GET_DATUM(agtype_value_to_agtype(new_path));
@@ -340,23 +393,29 @@ static void process_update_list(CustomScanState *node)
          * possible when the OPTIONAL MATCH clause is implemented.
          */
         if (scanTupleSlot->tts_isnull[update_item->entity_position - 1])
+        {
             continue;
+        }
 
         if (scanTupleSlot->tts_tupleDescriptor->attrs[update_item->entity_position -1].atttypid != AGTYPEOID)
+        {
             ereport(ERROR,
                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                      errmsg("age %s clause can only update agtype",
                             clause_name)));
+        }
 
         original_entity = DATUM_GET_AGTYPE_P(scanTupleSlot->tts_values[update_item->entity_position - 1]);
         original_entity_value = get_ith_agtype_value_from_container(&original_entity->root, 0);
 
         if (original_entity_value->type != AGTV_VERTEX &&
             original_entity_value->type != AGTV_EDGE)
+        {
             ereport(ERROR,
                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                      errmsg("age %s clause can only update vertex and edges",
                             clause_name)));
+        }
 
         /* get the id and label for later */
         id = GET_AGTYPE_VALUE_OBJECT_VALUE(original_entity_value, "id");
@@ -374,18 +433,26 @@ static void process_update_list(CustomScanState *node)
          * MATCH is implemented.
          */
         if(update_item->remove_item)
+        {
             remove_property = true;
+        }
         else
+        {
             remove_property = scanTupleSlot->tts_isnull[update_item->prop_position - 1];
+        }
 
         /*
          * If we need to remove the property, set the value to NULL. Otherwise
          * fetch the evaluated expression from the tuble slot.
          */
         if (remove_property)
+        {
             new_property_value = NULL;
+        }
         else
+        {
             new_property_value = DATUM_GET_AGTYPE_P(scanTupleSlot->tts_values[update_item->prop_position - 1]);
+        }
 
         /*
          * Alter the properties Agtype value to contain or remove the updated
@@ -508,7 +575,9 @@ static TupleTableSlot *exec_cypher_set(CustomScanState *node)
     Increment_Estate_CommandId(estate);
 
     if (TupIsNull(slot))
+    {
         return NULL;
+    }
 
     econtext->ecxt_scantuple =
         node->ss.ps.lefttree->ps_ProjInfo->pi_exprContext->ecxt_scantuple;
diff --git a/src/backend/utils/adt/agtype.c b/src/backend/utils/adt/agtype.c
index 6199c67..240ad72 100644
--- a/src/backend/utils/adt/agtype.c
+++ b/src/backend/utils/adt/agtype.c
@@ -165,6 +165,7 @@ static int extract_variadic_args_min(FunctionCallInfo fcinfo,
                                      int variadic_start, bool convert_unknown,
                                      Datum **args, Oid **types, bool **nulls,
                                      int min_num_args);
+agtype_value *agtype_composite_to_agtype_value_binary(agtype *a);
 
 /* fast helper function to test for AGTV_NULL in an agtype */
 bool is_agtype_null(agtype *agt_arg)
@@ -7937,7 +7938,37 @@ Datum age_timestamp(PG_FUNCTION_ARGS)
     PG_RETURN_POINTER(agtype_value_to_agtype(&agtv_result));
 }
 
-agtype_value *alter_property_value(agtype_value *properties, char *var_name, agtype *new_v, bool remove_property)
+/*
+ * Converts an agtype object or array to a binary agtype_value.
+ */
+agtype_value *agtype_composite_to_agtype_value_binary(agtype *a)
+{
+    agtype_value *result;
+
+    if (AGTYPE_CONTAINER_IS_SCALAR(&a->root))
+    {
+        ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+                        errmsg("cannot convert agtype scalar objects to binary agtype_value objects")));
+    }
+
+    result = palloc(sizeof(agtype_value));
+
+    // convert the agtype to a binary agtype_value
+    result->type = AGTV_BINARY;
+    result->val.binary.len = AGTYPE_CONTAINER_SIZE(&a->root);
+    result->val.binary.data = &a->root;
+
+    return result;
+}
+
+/*
+ * For the given properties, update the property with the key equal
+ * to var_name with the value defined in new_v. If the remove_property
+ * flag is set, simply remove the property with the given property
+ * name instead.
+ */
+agtype_value *alter_property_value(agtype_value *properties, char *var_name,
+                                   agtype *new_v, bool remove_property)
 {
     agtype_iterator *it;
     agtype_iterator_token tok = WAGT_DONE;
@@ -7947,12 +7978,18 @@ agtype_value *alter_property_value(agtype_value *properties, char *var_name, agt
     agtype_value *parsed_agtype_value = NULL;
     bool found;
 
+    // if no properties, return NULL
     if (properties == NULL)
+    {
         return NULL;
+    }
 
+    // if properties is not an object, throw an error
     if (properties->type != AGTV_OBJECT)
+    {
         ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                         errmsg("can only update objects")));
+    }
 
     r = palloc0(sizeof(agtype_value));
 
@@ -7962,8 +7999,14 @@ agtype_value *alter_property_value(agtype_value *properties, char *var_name, agt
 
     parsed_agtype_value = push_agtype_value(&parse_state, tok, tok < WAGT_BEGIN_ARRAY ? r : NULL);
 
+    /*
+     * If the new value is NULL, this is equivalent to the remove_property
+     * flag set to true.
+     */
     if (new_v == NULL)
+    {
         remove_property = true;
+    }
 
     found = false;
     while (true)
@@ -7973,36 +8016,68 @@ agtype_value *alter_property_value(agtype_value *properties, char *var_name, agt
         tok = agtype_iterator_next(&it, r, true);
 
         if (tok == WAGT_DONE || tok == WAGT_END_OBJECT)
+        {
             break;
+        }
 
         str = pnstrdup(r->val.string.val, r->val.string.len);
+
+        /*
+         * Check the key value, if it is equal to the passed in
+         * var_name, replace the value for this key with the passed
+         * in agtype. Otherwise pass the existing value to the
+         * new properties agtype_value.
+         */
         if (strcmp(str, var_name))
         {
+            // push the key
             parsed_agtype_value = push_agtype_value(
                 &parse_state, tok, tok < WAGT_BEGIN_ARRAY ? r : NULL);
 
+            // get the value and push the value
             tok = agtype_iterator_next(&it, r, true);
-
             parsed_agtype_value = push_agtype_value(&parse_state, tok, r);
         }
         else
         {
             agtype_value *new_agtype_value_v;
 
-            if (remove_property)
+            // if the remove flag is set, don't push the key or any value
+            if(remove_property)
             {
+                // skip the value
                 tok = agtype_iterator_next(&it, r, true);
                 continue;
             }
 
+            // push the key
             parsed_agtype_value = push_agtype_value(
                 &parse_state, tok, tok < WAGT_BEGIN_ARRAY ? r : NULL);
 
-            new_agtype_value_v = get_ith_agtype_value_from_container(&new_v->root, 0);
-
+            // skip the existing value for the key
             tok = agtype_iterator_next(&it, r, true);
 
-            parsed_agtype_value = push_agtype_value(&parse_state, tok, new_agtype_value_v);
+            /*
+             * If the the new agtype is scalar, push the agtype_value to the
+             * parse state. If the agtype is an object or array convert the
+             * agtype to a binary agtype_value to pass to the parse_state.
+             * This will save uncessary deserialization and serialization
+             * logic from running.
+             */
+            if (AGTYPE_CONTAINER_IS_SCALAR(&new_v->root))
+            {
+                //get the scalar value and push as the value
+                new_agtype_value_v = get_ith_agtype_value_from_container(&new_v->root, 0);
+
+                parsed_agtype_value = push_agtype_value(&parse_state, WAGT_VALUE, new_agtype_value_v);
+            }
+            else
+            {
+                agtype_value *result = agtype_composite_to_agtype_value_binary(new_v);
+
+                parsed_agtype_value = push_agtype_value(&parse_state, WAGT_VALUE, result);
+            }
+
             found = true;
         }
     }
@@ -8014,17 +8089,35 @@ agtype_value *alter_property_value(agtype_value *properties, char *var_name, agt
     if (!found && !remove_property)
     {
         agtype_value *new_agtype_value_v;
+        agtype_value *key = string_to_agtype_value(var_name);
 
+        // push the new key
         parsed_agtype_value = push_agtype_value(
-            &parse_state, WAGT_KEY, string_to_agtype_value(var_name));
+            &parse_state, WAGT_KEY, key);
 
-        new_agtype_value_v = get_ith_agtype_value_from_container(&new_v->root, 0);
+        /*
+         * If the the new agtype is scalar, push the agtype_value to the
+         * parse state. If the agtype is an object or array convert the
+         * agtype to a binary agtype_value to pass to the parse_state.
+         * This will save uncessary deserialization and serialization
+         * logic from running.
+         */
+        if (AGTYPE_CONTAINER_IS_SCALAR(&new_v->root))
+        {
+            new_agtype_value_v = get_ith_agtype_value_from_container(&new_v->root, 0);
 
-        tok = agtype_iterator_next(&it, r, true);
+            // convert the agtype array or object to a binary agtype_value
+            parsed_agtype_value = push_agtype_value(&parse_state, WAGT_VALUE, new_agtype_value_v);
+        }
+        else
+        {
+            agtype_value *result = agtype_composite_to_agtype_value_binary(new_v);
 
-        parsed_agtype_value = push_agtype_value(&parse_state, WAGT_VALUE, new_agtype_value_v);
+            parsed_agtype_value = push_agtype_value(&parse_state, WAGT_VALUE, result);
+        }
     }
 
+    // push the end object token to parse state
     parsed_agtype_value = push_agtype_value(&parse_state, WAGT_END_OBJECT, NULL);
 
     return parsed_agtype_value;