You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add the feature create_subgraph() for materialized induced-subgraph
extraction.
Add ag_catalog.create_subgraph(new_graph, from_graph, node_filter,
relationship_filter) which materializes a new, persistent, fully
Cypher-queryable AGE graph as the induced subgraph of an existing graph.
Selection follows the graph-theory induced-subgraph definition as
operationalized by Neo4j GDS gds.graph.filter():
* a vertex is kept iff node_filter holds ('*' keeps all);
* an edge is kept iff relationship_filter holds AND both of its
endpoints were kept (no dangling edges).
Filters are arbitrary Cypher predicates bound to `n` (nodes) and `r`
(relationships) and are evaluated by AGE's own Cypher engine against the
source graph, so the full predicate language is available; label
selection uses label(n)/label(r) since the match pattern is fixed.
Implementation notes:
* Result is a real, ACID, registered graph (create_graph + create_v/
elabel), not a virtual view; it composes with cypher() and itself.
* Entity graphids are reassigned from the destination labels' own
sequences (graphid encodes a per-graph label id), and edge endpoints
are remapped through an old->new vertex map, enforcing the induced
rule via inner joins.
* Source label tables are read with FROM ONLY to avoid double-copying
children under PostgreSQL table inheritance.
* Properties of any agtype are preserved; self-loops and parallel
edges (multigraph structure) are retained.
* SECURITY INVOKER: reads respect the caller's table privileges and
RLS; the new graph is owned by the caller.
* Validates NULL/identical graph names, missing source, pre-existing
destination, and a reserved dollar-quote token in predicates.
Wire-up:
* sql/age_subgraph.sql (new) registered in sql/sql_files after
age_pg_upgrade; identical body added to age--1.7.0--y.y.y.sql so the
upgrade-path catalog comparison matches.
* regress/sql/subgraph.sql + expected output (new), added to REGRESS.
Covers full copy, vertex-induced, node+rel, label-only edge drop,
bipartite, empty result, composability, self-loops/parallel edges,
property fidelity, and error cases over a ~4500-vertex / 2000-edge
source graph.
All 38 regression tests pass against PostgreSQL 18.
Co-authored-by: GitHub Copilot (Claude Opus 4.8) <[email protected]>
modified: Makefile
modified: age--1.7.0--y.y.y.sql
new file: regress/expected/subgraph.out
new file: regress/sql/subgraph.sql
new file: sql/age_subgraph.sql
modified: sql/sql_files
EXECUTE format('INSERT INTO %s (id, start_id, end_id, properties) '
1046
+
'SELECT new_id, new_start, new_end, props '
1047
+
'FROM _ag_sg_estage', dst_relation);
1048
+
GET DIAGNOSTICS inserted = ROW_COUNT;
1049
+
v_rel_count := v_rel_count + inserted;
1050
+
1051
+
DROPTABLE _ag_sg_estage;
1052
+
END LOOP;
1053
+
1054
+
RETURN QUERY SELECT v_node_count, v_rel_count;
1055
+
END;
1056
+
$function$;
1057
+
1058
+
COMMENT ON FUNCTION ag_catalog.create_subgraph(name, name, text, text) IS
1059
+
'Materializes a new persistent graph as the induced subgraph of from_graph selected by a Cypher node predicate (on n) and relationship predicate (on r); ''*'' keeps all. An edge is kept only if its predicate holds and both endpoints are kept. Returns (node_count, relationship_count).';
0 commit comments