gregfelice opened a new pull request, #2458:
URL: https://github.com/apache/age/pull/2458

   ## Problem
   
   Fixes #2450. A `GENERATED ALWAYS ... STORED` column on a label table caused 
a backend segfault (signal 11) on Cypher `CREATE` / `MERGE` / `SET`:
   
   ```sql
   SELECT create_graph('age_bug');
   SELECT create_vlabel('age_bug', 'Product');
   ALTER TABLE age_bug."Product"
     ADD COLUMN category varchar(25)
     GENERATED ALWAYS AS (agtype_access_operator(properties, '"category"')) 
STORED;
   -- crashes the backend:
   SELECT * FROM cypher('age_bug', $$ CREATE (p:Product {category:'disk'}) 
RETURN p $$) AS (p agtype);
   ```
   
   ## Root cause
   
   AGE builds the insert/update tuple slot from the **full** label-table 
descriptor (`table_slot_create`), but only populates the columns it manages — 
`id`/`properties` for vertices, `id`/`start_id`/`end_id`/`properties` for 
edges. Any user-added column is left as an uninitialized slot entry. 
`ExecStoreVirtualTuple` then marks all attributes valid, so `heap_form_tuple()` 
→ `heap_compute_data_size()` reads the uninitialized 
`tts_isnull[]`/`tts_values[]` and segfaults dereferencing garbage as a varlena.
   
   ```
   #0 heap_compute_data_size
   #1 heap_form_tuple
   #3 ExecFetchSlotHeapTuple
   #4 insert_entity_tuple_cid   cypher_utils.c
   #6 create_vertex            cypher_create.c
   ```
   
   The SET path crashes identically via `update_entity_tuple` (`cypher_set.c`). 
It affects both stored generated columns and plain `ADD COLUMN`s.
   
   ## Fix
   
   1. **`clear_entity_slot()`** clears the slot and marks every attribute NULL 
before AGE fills in its own columns, so columns AGE doesn't manage default to 
NULL instead of stale slot memory. Used at all six slot-build sites: 
`create_vertex`, `create_edge`, `merge_vertex`, `merge_edge`, and the 
`populate_vertex_tts` / `populate_edge_tts` helpers (SET).
   2. **`ExecComputeStoredGenerated()`** is called in `insert_entity_tuple_cid` 
(CREATE/MERGE, `CMD_INSERT`) and `update_entity_tuple` (SET, `CMD_UPDATE`) 
before the heap tuple is materialized when the relation has stored generated 
columns, so those columns are computed on insert and recomputed on update per 
PostgreSQL semantics.
   
   ## Testing
   
   New `generated_columns` regression test covering stored generated columns on 
vertex **and** edge labels across CREATE / MERGE / SET (values verified 
computed and recomputed), plus a plain user column that must not crash. Passes 
under `pg_regress`.
   
   Verified against the reporter's exact repro on PG18: no crash, and 
`category` correctly computes (`disk` on CREATE) and recomputes (`ssd` after 
SET).
   
   ## Note
   
   On `SET`, AGE rebuilds the row from `id`/`properties`, so a **generated** 
column recomputes correctly but a **plain** (non-generated) column is reset to 
NULL. Preserving plain-column values across updates would be a larger change 
and is out of scope here; the supported pattern is a `GENERATED ... STORED` 
column derived from `properties`.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to