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]