Skip to content

Cache ResultRelInfo per label in apply_update_list to avoid per-row generated-expr rebuild on SET #2459

Description

@gregfelice

Summary

The Cypher SET executor (apply_update_list in src/backend/executor/cypher_set.c) creates a fresh ResultRelInfo per updated entity via create_entity_result_rel_info() inside the per-row loop.

Now that SET computes stored generated columns (#2458, for #2450), ExecComputeStoredGenerated() lazily initializes ri_GeneratedExprsU on that ResultRelInfo. Because a new ResultRelInfo is built per row, a multi-row SET on a label with a stored generated column rebuilds the generated-column expression state on every row and retains it in the executor query context until query end.

Impact

  • Only affects SET on labels that actually have a GENERATED ALWAYS ... STORED column (the compute is guarded by has_generated_stored), so there is no regression for the common case.
  • For that case, expression-state setup is O(rows) instead of O(labels), with corresponding memory held for the duration of the query.

Proposed fix

Cache/reuse the ResultRelInfo per label (relation OID) for the lifetime of apply_update_list, mirroring the existing relation / index-OID / RLS caching already done there. That lets ri_GeneratedExprsU (and index/constraint setup) initialize once per relation instead of once per updated row.

Notes

Split out from the #2458 review (thanks @MuhammadTahaNaveed) to keep that bugfix focused. Not a correctness issue — a performance/memory improvement for multi-row SET on generated-column labels.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions