Skip to content

Conversation

@jrgemignani
Copy link
Contributor

NOTE: This PR was created with AI tools and a human.

Optimized id() and properties() field access on vertices and edges.

When accessing id(v) or properties(v) on a vertex, the system was generating inefficient SQL that rebuilt the entire vertex agtype before extracting the field:

age_id(_agtype_build_vertex(id, _label_name_from_table_oid(labels),
properties))

This forced full vertex reconstruction for every row, even though the data was already available in table columns.

Added optimize_vertex_field_access() in cypher_expr.c to detect these patterns and optimize them to direct column access:

  • age_id(_agtype_build_vertex(id, ...)) → graphid_to_agtype(id)
  • age_properties(_agtype_build_vertex(..., props)) → props
  • age_id(_agtype_build_edge(id, ...)) → graphid_to_agtype(id)
  • age_start_id(_agtype_build_edge(...)) → graphid_to_agtype(start_id)
  • age_end_id(_agtype_build_edge(...)) → graphid_to_agtype(end_id)
  • age_properties(_agtype_build_edge(...)) → props

Note: age_label() is intentionally not optimized due to complexity of cstring-to-agtype string conversion.

Added regression tests in unified_vertex_table.sql to verify the optimization works correctly for both vertices and edges.

modified: regress/expected/unified_vertex_table.out
modified: regress/sql/unified_vertex_table.sql
modified: src/backend/parser/cypher_expr.c

NOTE: This PR was created with AI tools and a human.

Optimized id() and properties() field access on vertices and edges.

When accessing id(v) or properties(v) on a vertex, the system was
generating inefficient SQL that rebuilt the entire vertex agtype
before extracting the field:

  age_id(_agtype_build_vertex(id, _label_name_from_table_oid(labels),
                              properties))

This forced full vertex reconstruction for every row, even though
the data was already available in table columns.

Added optimize_vertex_field_access() in cypher_expr.c to detect these
patterns and optimize them to direct column access:

  - age_id(_agtype_build_vertex(id, ...)) → graphid_to_agtype(id)
  - age_properties(_agtype_build_vertex(..., props)) → props
  - age_id(_agtype_build_edge(id, ...)) → graphid_to_agtype(id)
  - age_start_id(_agtype_build_edge(...)) → graphid_to_agtype(start_id)
  - age_end_id(_agtype_build_edge(...)) → graphid_to_agtype(end_id)
  - age_properties(_agtype_build_edge(...)) → props

Note: age_label() is intentionally not optimized due to complexity
of cstring-to-agtype string conversion.

Added regression tests in unified_vertex_table.sql to verify the
optimization works correctly for both vertices and edges.

modified:   regress/expected/unified_vertex_table.out
modified:   regress/sql/unified_vertex_table.sql
modified:   src/backend/parser/cypher_expr.c
@github-actions github-actions bot added the override-stale To keep issues/PRs untouched from stale action label Dec 23, 2025
@jrgemignani jrgemignani merged commit e384a96 into apache:Dev_Multiple_Labels Dec 23, 2025
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

override-stale To keep issues/PRs untouched from stale action

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant