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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions