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

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


The following commit(s) were added to refs/heads/master by this push:
     new 56a92d8c Fix Issue 1884: Ambiguous column reference (#2306)
56a92d8c is described below

commit 56a92d8c1be364e07bac51665a362ca91957194b
Author: John Gemignani <[email protected]>
AuthorDate: Sun Jan 18 10:02:55 2026 -0800

    Fix Issue 1884: Ambiguous column reference (#2306)
    
    Fix Issue 1884: Ambiguous column reference and invalid AGT header
    errors.
    
    Note: This PR was created with AI tools and a human, or 2.
    
    This commit addresses two related bugs that occur when using SET to store
    graph elements (vertices, edges, paths) as property values:
    
    Issue 1884 - "column reference is ambiguous" error:
    When a Cypher query uses the same variable in both the SET expression RHS
    and the RETURN clause (e.g., SET n.prop = n RETURN n), PostgreSQL would
    report "column reference is ambiguous" because the variable appeared in
    multiple subqueries without proper qualification.
    
    Solution: The fix for this issue was already in place through the target
    entry naming scheme that qualifies column references.
    
    "Invalid AGT header value" offset error:
    When deserializing nested VERTEX, EDGE, or PATH values stored in properties,
    the system would fail with errors like "Invalid AGT header value: 
0x00000041".
    This occurred because ag_serialize_extended_type() did not include alignment
    padding (padlen) in the agtentry length calculation for these types, while
    fill_agtype_value() uses INTALIGN() when reading, causing offset mismatch.
    
    Solution: Modified ag_serialize_extended_type() in agtype_ext.c to include
    padlen in the agtentry length for VERTEX, EDGE, and PATH cases, matching
    the existing pattern used for INTEGER, FLOAT, and NUMERIC types:
    
        *agtentry = AGTENTRY_IS_AGTYPE | (padlen + (AGTENTRY_OFFLENMASK & ...));
    
    This ensures the serialized length accounts for alignment padding, allowing
    correct deserialization of nested graph elements.
    
    Appropriate regression tests were added to verify the fixes.
    
    Co-authored by: Zainab Saad <[email protected]>
    
    modified:   regress/expected/cypher_set.out
    modified:   regress/sql/cypher_set.sql
    modified:   src/backend/parser/cypher_clause.c
    modified:   src/backend/utils/adt/agtype_ext.c
---
 regress/expected/cypher_set.out    | 266 +++++++++++++++++++++++++++++++++++++
 regress/sql/cypher_set.sql         | 164 +++++++++++++++++++++++
 src/backend/parser/cypher_clause.c |  19 ++-
 src/backend/utils/adt/agtype_ext.c |   8 +-
 4 files changed, 451 insertions(+), 6 deletions(-)

diff --git a/regress/expected/cypher_set.out b/regress/expected/cypher_set.out
index 1d24a7f9..239234ed 100644
--- a/regress/expected/cypher_set.out
+++ b/regress/expected/cypher_set.out
@@ -988,6 +988,245 @@ SELECT * FROM cypher('issue_1634', $$ MATCH (u) DELETE 
(u) $$) AS (u agtype);
 ---
 (0 rows)
 
+--
+-- Issue 1884: column reference is ambiguous when using same variable in
+--             SET expression and RETURN clause
+--
+-- These tests cover:
+-- 1. "column reference is ambiguous" error when variable is used in both
+--    SET expression RHS (e.g., SET n.prop = n) and RETURN clause
+-- 2. "Invalid AGT header value" error caused by incorrect offset calculation
+--    when nested VERTEX/EDGE/PATH values are serialized in properties
+--
+-- Tests use isolated data to keep output manageable and avoid cumulative 
nesting
+--
+SELECT * FROM create_graph('issue_1884');
+NOTICE:  graph "issue_1884" has been created
+ create_graph 
+--------------
+ 
+(1 row)
+
+-- ============================================================================
+-- Test Group A: Basic "column reference is ambiguous" fix (Issue 1884)
+-- ============================================================================
+-- Test A1: Core issue - SET n.prop = n with RETURN n (the original bug)
+SELECT * FROM cypher('issue_1884', $$
+    CREATE (n:TestA1 {name: 'A1'})
+    SET n.self = n
+    RETURN n
+$$) AS (result agtype);
+                                                                               
    result                                                                      
             
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ {"id": 844424930131969, "label": "TestA1", "properties": {"name": "A1", 
"self": {"id": 844424930131969, "label": "TestA1", "properties": {"name": 
"A1"}}::vertex}}::vertex
+(1 row)
+
+-- Test A2: Multiple variables in SET and RETURN
+SELECT * FROM cypher('issue_1884', $$
+    CREATE (a:TestA2 {name: 'A'})-[e:LINK {w: 1}]->(b:TestA2 {name: 'B'})
+    SET a.edge = e, b.edge = e
+    RETURN a, e, b
+$$) AS (a agtype, e agtype, b agtype);
+                                                                               
                               a                                                
                                                              |                 
                                                e                               
                                  |                                             
                                                                 b              
              [...]
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------
 [...]
+ {"id": 1125899906842625, "label": "TestA2", "properties": {"edge": {"id": 
1407374883553281, "label": "LINK", "end_id": 1125899906842626, "start_id": 
1125899906842625, "properties": {"w": 1}}::edge, "name": "A"}}::vertex | {"id": 
1407374883553281, "label": "LINK", "end_id": 1125899906842626, "start_id": 
1125899906842625, "properties": {"w": 1}}::edge | {"id": 1125899906842626, 
"label": "TestA2", "properties": {"edge": {"id": 1407374883553281, "label": 
"LINK", "end_id": 1125899906842626,  [...]
+(1 row)
+
+-- Test A3: SET edge property to node reference
+SELECT * FROM cypher('issue_1884', $$
+    CREATE (a:TestA3 {name: 'X'})-[e:REL]->(b:TestA3 {name: 'Y'})
+    SET e.src = a, e.dst = b
+    RETURN e
+$$) AS (e agtype);
+                                                                               
                                                                      e         
                                                                                
                                                             
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ {"id": 1970324836974593, "label": "REL", "end_id": 1688849860263938, 
"start_id": 1688849860263937, "properties": {"dst": {"id": 1688849860263938, 
"label": "TestA3", "properties": {"name": "Y"}}::vertex, "src": {"id": 
1688849860263937, "label": "TestA3", "properties": {"name": 
"X"}}::vertex}}::edge
+(1 row)
+
+-- ============================================================================
+-- Test Group B: Nested VERTEX/EDGE/PATH serialization (offset error fix)
+-- ============================================================================
+-- Test B1: Vertex nested in vertex property (tests VERTEX serialization)
+SELECT * FROM cypher('issue_1884', $$
+    CREATE (n:TestB1 {val: 1})
+    SET n.copy = n
+    RETURN n
+$$) AS (result agtype);
+                                                                               
 result                                                                         
       
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ {"id": 2251799813685249, "label": "TestB1", "properties": {"val": 1, "copy": 
{"id": 2251799813685249, "label": "TestB1", "properties": {"val": 
1}}::vertex}}::vertex
+(1 row)
+
+-- Verify nested vertex can be read back
+SELECT * FROM cypher('issue_1884', $$
+    MATCH (n:TestB1)
+    RETURN n.copy
+$$) AS (copy agtype);
+                                     copy                                      
+-------------------------------------------------------------------------------
+ {"id": 2251799813685249, "label": "TestB1", "properties": {"val": 1}}::vertex
+(1 row)
+
+-- Test B2: Edge nested in node property (tests EDGE serialization)
+SELECT * FROM cypher('issue_1884', $$
+    CREATE (a:TestB2 {name: 'start'})-[e:B2REL {x: 100}]->(b:TestB2 {name: 
'end'})
+    SET a.myEdge = e
+    RETURN a
+$$) AS (a agtype);
+                                                                               
                                   a                                            
                                                                       
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ {"id": 2533274790395905, "label": "TestB2", "properties": {"name": "start", 
"myEdge": {"id": 2814749767106561, "label": "B2REL", "end_id": 
2533274790395906, "start_id": 2533274790395905, "properties": {"x": 
100}}::edge}}::vertex
+(1 row)
+
+-- Verify nested edge can be read back
+SELECT * FROM cypher('issue_1884', $$
+    MATCH (n:TestB2 {name: 'start'})
+    RETURN n.myEdge
+$$) AS (edge agtype);
+                                                                 edge          
                                                       
+--------------------------------------------------------------------------------------------------------------------------------------
+ {"id": 2814749767106561, "label": "B2REL", "end_id": 2533274790395906, 
"start_id": 2533274790395905, "properties": {"x": 100}}::edge
+(1 row)
+
+-- Test B3: Path nested in node property (tests PATH serialization)
+-- First create the pattern
+SELECT * FROM cypher('issue_1884', $$
+    CREATE (a:TestB3)-[e:B3REL]->(b:TestB3)
+    RETURN a
+$$) AS (a agtype);
+                                   a                                   
+-----------------------------------------------------------------------
+ {"id": 3096224743817217, "label": "TestB3", "properties": {}}::vertex
+(1 row)
+
+-- Then match the path and set it (MATCH only sees committed data)
+SELECT * FROM cypher('issue_1884', $$
+    MATCH p = (a:TestB3)-[e:B3REL]->(b:TestB3)
+    SET a.myPath = p
+    RETURN a
+$$) AS (a agtype);
+                                                                               
                                                                                
                  a                                                             
                                                                                
                                    
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ {"id": 3096224743817217, "label": "TestB3", "properties": {"myPath": [{"id": 
3096224743817217, "label": "TestB3", "properties": {}}::vertex, {"id": 
3377699720527873, "label": "B3REL", "end_id": 3096224743817218, "start_id": 
3096224743817217, "properties": {}}::edge, {"id": 3096224743817218, "label": 
"TestB3", "properties": {}}::vertex]::path}}::vertex
+(1 row)
+
+-- Verify nested path can be read back
+SELECT * FROM cypher('issue_1884', $$
+    MATCH (n:TestB3)
+    WHERE n.myPath IS NOT NULL
+    RETURN n.myPath
+$$) AS (path agtype);
+                                                                               
                                                         path                   
                                                                                
                                     
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ [{"id": 3096224743817217, "label": "TestB3", "properties": {}}::vertex, 
{"id": 3377699720527873, "label": "B3REL", "end_id": 3096224743817218, 
"start_id": 3096224743817217, "properties": {}}::edge, {"id": 3096224743817218, 
"label": "TestB3", "properties": {}}::vertex]::path
+(1 row)
+
+-- ============================================================================
+-- Test Group C: Nested structures in arrays and maps
+-- ============================================================================
+-- Test C1: Vertex in array
+SELECT * FROM cypher('issue_1884', $$
+    CREATE (n:TestC1 {tag: 'arrtest'})
+    SET n.arr = [n]
+    RETURN n
+$$) AS (result agtype);
+                                                                               
         result                                                                 
                        
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ {"id": 3659174697238529, "label": "TestC1", "properties": {"arr": [{"id": 
3659174697238529, "label": "TestC1", "properties": {"tag": 
"arrtest"}}::vertex], "tag": "arrtest"}}::vertex
+(1 row)
+
+-- Verify array with nested vertex
+SELECT * FROM cypher('issue_1884', $$
+    MATCH (n:TestC1)
+    RETURN n.arr[0]
+$$) AS (elem agtype);
+                                         elem                                  
        
+---------------------------------------------------------------------------------------
+ {"id": 3659174697238529, "label": "TestC1", "properties": {"tag": 
"arrtest"}}::vertex
+(1 row)
+
+-- Test C2: Vertex in map
+SELECT * FROM cypher('issue_1884', $$
+    CREATE (n:TestC2 {tag: 'maptest'})
+    SET n.obj = {node: n}
+    RETURN n
+$$) AS (result agtype);
+                                                                               
             result                                                             
                                
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ {"id": 3940649673949185, "label": "TestC2", "properties": {"obj": {"node": 
{"id": 3940649673949185, "label": "TestC2", "properties": {"tag": 
"maptest"}}::vertex}, "tag": "maptest"}}::vertex
+(1 row)
+
+-- Verify map with nested vertex
+SELECT * FROM cypher('issue_1884', $$
+    MATCH (n:TestC2)
+    RETURN n.obj.node
+$$) AS (node agtype);
+                                         node                                  
        
+---------------------------------------------------------------------------------------
+ {"id": 3940649673949185, "label": "TestC2", "properties": {"tag": 
"maptest"}}::vertex
+(1 row)
+
+-- ============================================================================
+-- Test Group D: MERGE and CREATE with self-reference
+-- ============================================================================
+-- Test D1: MERGE with SET self-reference
+SELECT * FROM cypher('issue_1884', $$
+    MERGE (n:TestD1 {name: 'merged'})
+    SET n.ref = n
+    RETURN n
+$$) AS (result agtype);
+                                                                               
        result                                                                  
                      
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ {"id": 4222124650659841, "label": "TestD1", "properties": {"ref": {"id": 
4222124650659841, "label": "TestD1", "properties": {"name": "merged"}}::vertex, 
"name": "merged"}}::vertex
+(1 row)
+
+-- Test D2: CREATE with SET self-reference
+SELECT * FROM cypher('issue_1884', $$
+    CREATE (n:TestD2 {name: 'created'})
+    SET n.ref = n
+    RETURN n
+$$) AS (result agtype);
+                                                                               
         result                                                                 
                        
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ {"id": 4503599627370497, "label": "TestD2", "properties": {"ref": {"id": 
4503599627370497, "label": "TestD2", "properties": {"name": 
"created"}}::vertex, "name": "created"}}::vertex
+(1 row)
+
+-- ============================================================================
+-- Test Group E: Functions with variable references
+-- ============================================================================
+-- Test E1: id() and label() functions
+SELECT * FROM cypher('issue_1884', $$
+    CREATE (n:TestE1 {name: 'functest'})
+    SET n.myId = id(n), n.myLabel = label(n)
+    RETURN n
+$$) AS (result agtype);
+                                                                 result        
                                                         
+----------------------------------------------------------------------------------------------------------------------------------------
+ {"id": 4785074604081153, "label": "TestE1", "properties": {"myId": 
4785074604081153, "name": "functest", "myLabel": "TestE1"}}::vertex
+(1 row)
+
+-- Test E2: nodes() and relationships() with path
+-- First create the pattern
+SELECT * FROM cypher('issue_1884', $$
+    CREATE (a:TestE2)-[e:E2REL]->(b:TestE2)
+    RETURN a
+$$) AS (a agtype);
+                                   a                                   
+-----------------------------------------------------------------------
+ {"id": 5066549580791809, "label": "TestE2", "properties": {}}::vertex
+(1 row)
+
+-- Then match the path and extract nodes/relationships (MATCH only sees 
committed data)
+SELECT * FROM cypher('issue_1884', $$
+    MATCH p = (a:TestE2)-[e:E2REL]->(b:TestE2)
+    SET a.pathNodes = nodes(p), a.pathRels = relationships(p)
+    RETURN a
+$$) AS (a agtype);
+                                                                               
                                                                                
                       a                                                        
                                                                                
                                               
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ {"id": 5066549580791809, "label": "TestE2", "properties": {"pathRels": 
[{"id": 5348024557502465, "label": "E2REL", "end_id": 5066549580791810, 
"start_id": 5066549580791809, "properties": {}}::edge], "pathNodes": [{"id": 
5066549580791809, "label": "TestE2", "properties": {}}::vertex, {"id": 
5066549580791810, "label": "TestE2", "properties": {}}::vertex]}}::vertex
+(1 row)
+
 --
 -- Clean up
 --
@@ -1038,6 +1277,33 @@ NOTICE:  graph "issue_1634" has been dropped
  
 (1 row)
 
+SELECT drop_graph('issue_1884', true);
+NOTICE:  drop cascades to 19 other objects
+DETAIL:  drop cascades to table issue_1884._ag_label_vertex
+drop cascades to table issue_1884._ag_label_edge
+drop cascades to table issue_1884."TestA1"
+drop cascades to table issue_1884."TestA2"
+drop cascades to table issue_1884."LINK"
+drop cascades to table issue_1884."TestA3"
+drop cascades to table issue_1884."REL"
+drop cascades to table issue_1884."TestB1"
+drop cascades to table issue_1884."TestB2"
+drop cascades to table issue_1884."B2REL"
+drop cascades to table issue_1884."TestB3"
+drop cascades to table issue_1884."B3REL"
+drop cascades to table issue_1884."TestC1"
+drop cascades to table issue_1884."TestC2"
+drop cascades to table issue_1884."TestD1"
+drop cascades to table issue_1884."TestD2"
+drop cascades to table issue_1884."TestE1"
+drop cascades to table issue_1884."TestE2"
+drop cascades to table issue_1884."E2REL"
+NOTICE:  graph "issue_1884" has been dropped
+ drop_graph 
+------------
+ 
+(1 row)
+
 --
 -- End
 --
diff --git a/regress/sql/cypher_set.sql b/regress/sql/cypher_set.sql
index a2667153..e745d5d6 100644
--- a/regress/sql/cypher_set.sql
+++ b/regress/sql/cypher_set.sql
@@ -379,6 +379,169 @@ SELECT * FROM cypher('issue_1634', $$ MERGE (v:PERSION 
{id: '1'})
 
 SELECT * FROM cypher('issue_1634', $$ MATCH (u) DELETE (u) $$) AS (u agtype);
 
+--
+-- Issue 1884: column reference is ambiguous when using same variable in
+--             SET expression and RETURN clause
+--
+-- These tests cover:
+-- 1. "column reference is ambiguous" error when variable is used in both
+--    SET expression RHS (e.g., SET n.prop = n) and RETURN clause
+-- 2. "Invalid AGT header value" error caused by incorrect offset calculation
+--    when nested VERTEX/EDGE/PATH values are serialized in properties
+--
+-- Tests use isolated data to keep output manageable and avoid cumulative 
nesting
+--
+SELECT * FROM create_graph('issue_1884');
+
+-- ============================================================================
+-- Test Group A: Basic "column reference is ambiguous" fix (Issue 1884)
+-- ============================================================================
+
+-- Test A1: Core issue - SET n.prop = n with RETURN n (the original bug)
+SELECT * FROM cypher('issue_1884', $$
+    CREATE (n:TestA1 {name: 'A1'})
+    SET n.self = n
+    RETURN n
+$$) AS (result agtype);
+
+-- Test A2: Multiple variables in SET and RETURN
+SELECT * FROM cypher('issue_1884', $$
+    CREATE (a:TestA2 {name: 'A'})-[e:LINK {w: 1}]->(b:TestA2 {name: 'B'})
+    SET a.edge = e, b.edge = e
+    RETURN a, e, b
+$$) AS (a agtype, e agtype, b agtype);
+
+-- Test A3: SET edge property to node reference
+SELECT * FROM cypher('issue_1884', $$
+    CREATE (a:TestA3 {name: 'X'})-[e:REL]->(b:TestA3 {name: 'Y'})
+    SET e.src = a, e.dst = b
+    RETURN e
+$$) AS (e agtype);
+
+-- ============================================================================
+-- Test Group B: Nested VERTEX/EDGE/PATH serialization (offset error fix)
+-- ============================================================================
+
+-- Test B1: Vertex nested in vertex property (tests VERTEX serialization)
+SELECT * FROM cypher('issue_1884', $$
+    CREATE (n:TestB1 {val: 1})
+    SET n.copy = n
+    RETURN n
+$$) AS (result agtype);
+
+-- Verify nested vertex can be read back
+SELECT * FROM cypher('issue_1884', $$
+    MATCH (n:TestB1)
+    RETURN n.copy
+$$) AS (copy agtype);
+
+-- Test B2: Edge nested in node property (tests EDGE serialization)
+SELECT * FROM cypher('issue_1884', $$
+    CREATE (a:TestB2 {name: 'start'})-[e:B2REL {x: 100}]->(b:TestB2 {name: 
'end'})
+    SET a.myEdge = e
+    RETURN a
+$$) AS (a agtype);
+
+-- Verify nested edge can be read back
+SELECT * FROM cypher('issue_1884', $$
+    MATCH (n:TestB2 {name: 'start'})
+    RETURN n.myEdge
+$$) AS (edge agtype);
+
+-- Test B3: Path nested in node property (tests PATH serialization)
+-- First create the pattern
+SELECT * FROM cypher('issue_1884', $$
+    CREATE (a:TestB3)-[e:B3REL]->(b:TestB3)
+    RETURN a
+$$) AS (a agtype);
+
+-- Then match the path and set it (MATCH only sees committed data)
+SELECT * FROM cypher('issue_1884', $$
+    MATCH p = (a:TestB3)-[e:B3REL]->(b:TestB3)
+    SET a.myPath = p
+    RETURN a
+$$) AS (a agtype);
+
+-- Verify nested path can be read back
+SELECT * FROM cypher('issue_1884', $$
+    MATCH (n:TestB3)
+    WHERE n.myPath IS NOT NULL
+    RETURN n.myPath
+$$) AS (path agtype);
+
+-- ============================================================================
+-- Test Group C: Nested structures in arrays and maps
+-- ============================================================================
+
+-- Test C1: Vertex in array
+SELECT * FROM cypher('issue_1884', $$
+    CREATE (n:TestC1 {tag: 'arrtest'})
+    SET n.arr = [n]
+    RETURN n
+$$) AS (result agtype);
+
+-- Verify array with nested vertex
+SELECT * FROM cypher('issue_1884', $$
+    MATCH (n:TestC1)
+    RETURN n.arr[0]
+$$) AS (elem agtype);
+
+-- Test C2: Vertex in map
+SELECT * FROM cypher('issue_1884', $$
+    CREATE (n:TestC2 {tag: 'maptest'})
+    SET n.obj = {node: n}
+    RETURN n
+$$) AS (result agtype);
+
+-- Verify map with nested vertex
+SELECT * FROM cypher('issue_1884', $$
+    MATCH (n:TestC2)
+    RETURN n.obj.node
+$$) AS (node agtype);
+
+-- ============================================================================
+-- Test Group D: MERGE and CREATE with self-reference
+-- ============================================================================
+
+-- Test D1: MERGE with SET self-reference
+SELECT * FROM cypher('issue_1884', $$
+    MERGE (n:TestD1 {name: 'merged'})
+    SET n.ref = n
+    RETURN n
+$$) AS (result agtype);
+
+-- Test D2: CREATE with SET self-reference
+SELECT * FROM cypher('issue_1884', $$
+    CREATE (n:TestD2 {name: 'created'})
+    SET n.ref = n
+    RETURN n
+$$) AS (result agtype);
+
+-- ============================================================================
+-- Test Group E: Functions with variable references
+-- ============================================================================
+
+-- Test E1: id() and label() functions
+SELECT * FROM cypher('issue_1884', $$
+    CREATE (n:TestE1 {name: 'functest'})
+    SET n.myId = id(n), n.myLabel = label(n)
+    RETURN n
+$$) AS (result agtype);
+
+-- Test E2: nodes() and relationships() with path
+-- First create the pattern
+SELECT * FROM cypher('issue_1884', $$
+    CREATE (a:TestE2)-[e:E2REL]->(b:TestE2)
+    RETURN a
+$$) AS (a agtype);
+
+-- Then match the path and extract nodes/relationships (MATCH only sees 
committed data)
+SELECT * FROM cypher('issue_1884', $$
+    MATCH p = (a:TestE2)-[e:E2REL]->(b:TestE2)
+    SET a.pathNodes = nodes(p), a.pathRels = relationships(p)
+    RETURN a
+$$) AS (a agtype);
+
 --
 -- Clean up
 --
@@ -387,6 +550,7 @@ DROP FUNCTION set_test;
 SELECT drop_graph('cypher_set', true);
 SELECT drop_graph('cypher_set_1', true);
 SELECT drop_graph('issue_1634', true);
+SELECT drop_graph('issue_1884', true);
 
 --
 -- End
diff --git a/src/backend/parser/cypher_clause.c 
b/src/backend/parser/cypher_clause.c
index a5413bda..515f8c1d 100644
--- a/src/backend/parser/cypher_clause.c
+++ b/src/backend/parser/cypher_clause.c
@@ -71,6 +71,7 @@
 #define AGE_VARNAME_MERGE_CLAUSE AGE_DEFAULT_VARNAME_PREFIX"merge_clause"
 #define AGE_VARNAME_ID AGE_DEFAULT_VARNAME_PREFIX"id"
 #define AGE_VARNAME_SET_CLAUSE AGE_DEFAULT_VARNAME_PREFIX"set_clause"
+#define AGE_VARNAME_SET_VALUE AGE_DEFAULT_VARNAME_PREFIX"set_value"
 
 /*
  * In the transformation stage, we need to track
@@ -1911,10 +1912,24 @@ cypher_update_information 
*transform_cypher_set_item_list(
             ((cypher_map*)set_item->expr)->keep_null = set_item->is_add;
         }
 
-        /* create target entry for the new property value */
+        /*
+         * Create target entry for the new property value.
+         *
+         * We use a hidden variable name (AGE_VARNAME_SET_VALUE) for the
+         * SET expression value to prevent column name conflicts. This is
+         * necessary when the same variable is used on both the LHS and RHS
+         * of a SET clause (e.g., SET n.prop = n). Without this, the column
+         * name derived from the expression (e.g., "n") would duplicate the
+         * existing column name from the MATCH clause, causing a "column
+         * reference is ambiguous" error in subsequent clauses like RETURN.
+         *
+         * The hidden variable name will be filtered out by expand_pnsi_attrs
+         * when the targetlist is expanded for subsequent clauses.
+         */
         item->prop_position = (AttrNumber)pstate->p_next_resno;
         target_item = transform_cypher_item(cpstate, set_item->expr, NULL,
-                                            EXPR_KIND_SELECT_TARGET, NULL,
+                                            EXPR_KIND_SELECT_TARGET,
+                                            AGE_VARNAME_SET_VALUE,
                                             false);
 
         if (nodeTag(target_item->expr) == T_Aggref)
diff --git a/src/backend/utils/adt/agtype_ext.c 
b/src/backend/utils/adt/agtype_ext.c
index 8fc6600d..7a0ea991 100644
--- a/src/backend/utils/adt/agtype_ext.c
+++ b/src/backend/utils/adt/agtype_ext.c
@@ -89,7 +89,7 @@ bool ag_serialize_extended_type(StringInfo buffer, agtentry 
*agtentry,
         object_ae += pad_buffer_to_int(buffer);
 
         *agtentry = AGTENTRY_IS_AGTYPE |
-                    ((AGTENTRY_OFFLENMASK & (int)object_ae) + AGT_HEADER_SIZE);
+                    (padlen + (AGTENTRY_OFFLENMASK & (int)object_ae) + 
AGT_HEADER_SIZE);
         break;
     }
 
@@ -109,7 +109,7 @@ bool ag_serialize_extended_type(StringInfo buffer, agtentry 
*agtentry,
         object_ae += pad_buffer_to_int(buffer);
 
         *agtentry = AGTENTRY_IS_AGTYPE |
-                    ((AGTENTRY_OFFLENMASK & (int)object_ae) + AGT_HEADER_SIZE);
+                    (padlen + (AGTENTRY_OFFLENMASK & (int)object_ae) + 
AGT_HEADER_SIZE);
         break;
     }
 
@@ -129,7 +129,7 @@ bool ag_serialize_extended_type(StringInfo buffer, agtentry 
*agtentry,
         object_ae += pad_buffer_to_int(buffer);
 
         *agtentry = AGTENTRY_IS_AGTYPE |
-                    ((AGTENTRY_OFFLENMASK & (int)object_ae) + AGT_HEADER_SIZE);
+                    (padlen + (AGTENTRY_OFFLENMASK & (int)object_ae) + 
AGT_HEADER_SIZE);
         break;
     }
 
@@ -175,7 +175,7 @@ void ag_deserialize_extended_type(char *base_addr, uint32 
offset,
         break;
 
     default:
-        elog(ERROR, "Invalid AGT header value.");
+        ereport(ERROR, (errmsg("Invalid AGT header value: 0x%08x", 
agt_header)));
     }
 }
 

Reply via email to