Skip to content

Commit 9d6a08b

Browse files
Add vertex and edge composite types with direct field access optimization
- Introduce vertex and edge as pg composite types vertex: (id, label, properties) edge: (id, label, start_id, end_id, properties) - Property access (a.name) now directly uses a.properties for agtype_access_operator instead of rebuilding via _agtype_build_vertex/edge - Optimize accessor functions (id, properties, label, type, start_id, end_id) to use direct FieldSelect on composite types instead of agtype functions - Add casts: vertex/edge to agtype, vertex/edge to json/jsonb - Add eq and not eq ops for vertex/edge composite types. - Fix label_name specific routine to use cache instead of ag_label scan - Write/update clauses have executors strictly tied to agtype, due to which the variables after any write/update clause are carried forward as agtype. - Allows users to completely skip agtype build functions and return vertex/edge for pure read queries. - Change _label_name to return agtype since record comparisons are not allowed with cstring. Consequently, _agtype_build_vertex/edge now accept agtype as label. - Fix MERGE clause type mismatch when accessing properties from previous MATCH clauses by wrapping columns with agtype_volatile_wrapper before namespace lookup. - Update expression index in pgvector.sql, since now it uses raw properties column instead of _agtype_build_vertex/edge. - Add regression tests Assisted-by AI
1 parent 7beb653 commit 9d6a08b

File tree

24 files changed

+3607
-341
lines changed

24 files changed

+3607
-341
lines changed

age--1.6.0--y.y.y.sql

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,223 @@ CREATE FUNCTION ag_catalog._ag_enforce_edge_uniqueness4(graphid, graphid, graphi
5151
STABLE
5252
PARALLEL SAFE
5353
as 'MODULE_PATHNAME';
54+
55+
--
56+
-- Composite types for vertex and edge
57+
--
58+
CREATE TYPE ag_catalog.vertex AS (
59+
id graphid,
60+
label agtype,
61+
properties agtype
62+
);
63+
64+
CREATE TYPE ag_catalog.edge AS (
65+
id graphid,
66+
label agtype,
67+
end_id graphid,
68+
start_id graphid,
69+
properties agtype
70+
);
71+
72+
--
73+
-- vertex/edge to agtype cast functions
74+
--
75+
CREATE FUNCTION ag_catalog.vertex_to_agtype(vertex)
76+
RETURNS agtype
77+
LANGUAGE c
78+
IMMUTABLE
79+
RETURNS NULL ON NULL INPUT
80+
PARALLEL SAFE
81+
AS 'MODULE_PATHNAME';
82+
83+
CREATE FUNCTION ag_catalog.edge_to_agtype(edge)
84+
RETURNS agtype
85+
LANGUAGE c
86+
IMMUTABLE
87+
RETURNS NULL ON NULL INPUT
88+
PARALLEL SAFE
89+
AS 'MODULE_PATHNAME';
90+
91+
--
92+
-- Implicit casts from vertex/edge to agtype
93+
--
94+
CREATE CAST (vertex AS agtype)
95+
WITH FUNCTION ag_catalog.vertex_to_agtype(vertex)
96+
AS IMPLICIT;
97+
98+
CREATE CAST (edge AS agtype)
99+
WITH FUNCTION ag_catalog.edge_to_agtype(edge)
100+
AS IMPLICIT;
101+
102+
CREATE FUNCTION ag_catalog.vertex_to_json(vertex)
103+
RETURNS json
104+
LANGUAGE c
105+
IMMUTABLE
106+
RETURNS NULL ON NULL INPUT
107+
PARALLEL SAFE
108+
AS 'MODULE_PATHNAME';
109+
110+
CREATE FUNCTION ag_catalog.edge_to_json(edge)
111+
RETURNS json
112+
LANGUAGE c
113+
IMMUTABLE
114+
RETURNS NULL ON NULL INPUT
115+
PARALLEL SAFE
116+
AS 'MODULE_PATHNAME';
117+
118+
CREATE CAST (vertex AS json)
119+
WITH FUNCTION ag_catalog.vertex_to_json(vertex);
120+
121+
CREATE CAST (edge AS json)
122+
WITH FUNCTION ag_catalog.edge_to_json(edge);
123+
124+
CREATE FUNCTION ag_catalog.vertex_to_jsonb(vertex)
125+
RETURNS jsonb
126+
LANGUAGE c
127+
IMMUTABLE
128+
RETURNS NULL ON NULL INPUT
129+
PARALLEL SAFE
130+
AS 'MODULE_PATHNAME';
131+
132+
CREATE FUNCTION ag_catalog.edge_to_jsonb(edge)
133+
RETURNS jsonb
134+
LANGUAGE c
135+
IMMUTABLE
136+
RETURNS NULL ON NULL INPUT
137+
PARALLEL SAFE
138+
AS 'MODULE_PATHNAME';
139+
140+
CREATE CAST (vertex AS jsonb)
141+
WITH FUNCTION ag_catalog.vertex_to_jsonb(vertex);
142+
143+
CREATE CAST (edge AS jsonb)
144+
WITH FUNCTION ag_catalog.edge_to_jsonb(edge);
145+
146+
--
147+
-- Equality operators for vertex and edge (compare by id)
148+
--
149+
CREATE FUNCTION ag_catalog.vertex_eq(vertex, vertex)
150+
RETURNS boolean
151+
LANGUAGE sql
152+
IMMUTABLE
153+
RETURNS NULL ON NULL INPUT
154+
PARALLEL SAFE
155+
AS $$ SELECT $1.id = $2.id $$;
156+
157+
CREATE OPERATOR = (
158+
FUNCTION = ag_catalog.vertex_eq,
159+
LEFTARG = vertex,
160+
RIGHTARG = vertex,
161+
COMMUTATOR = =,
162+
NEGATOR = <>,
163+
RESTRICT = eqsel,
164+
JOIN = eqjoinsel,
165+
HASHES,
166+
MERGES
167+
);
168+
169+
CREATE FUNCTION ag_catalog.vertex_ne(vertex, vertex)
170+
RETURNS boolean
171+
LANGUAGE sql
172+
IMMUTABLE
173+
RETURNS NULL ON NULL INPUT
174+
PARALLEL SAFE
175+
AS $$ SELECT $1.id <> $2.id $$;
176+
177+
CREATE OPERATOR <> (
178+
FUNCTION = ag_catalog.vertex_ne,
179+
LEFTARG = vertex,
180+
RIGHTARG = vertex,
181+
COMMUTATOR = <>,
182+
NEGATOR = =,
183+
RESTRICT = neqsel,
184+
JOIN = neqjoinsel
185+
);
186+
187+
CREATE FUNCTION ag_catalog.edge_eq(edge, edge)
188+
RETURNS boolean
189+
LANGUAGE sql
190+
IMMUTABLE
191+
RETURNS NULL ON NULL INPUT
192+
PARALLEL SAFE
193+
AS $$ SELECT $1.id = $2.id $$;
194+
195+
CREATE OPERATOR = (
196+
FUNCTION = ag_catalog.edge_eq,
197+
LEFTARG = edge,
198+
RIGHTARG = edge,
199+
COMMUTATOR = =,
200+
NEGATOR = <>,
201+
RESTRICT = eqsel,
202+
JOIN = eqjoinsel,
203+
HASHES,
204+
MERGES
205+
);
206+
207+
CREATE FUNCTION ag_catalog.edge_ne(edge, edge)
208+
RETURNS boolean
209+
LANGUAGE sql
210+
IMMUTABLE
211+
RETURNS NULL ON NULL INPUT
212+
PARALLEL SAFE
213+
AS $$ SELECT $1.id <> $2.id $$;
214+
215+
CREATE OPERATOR <> (
216+
FUNCTION = ag_catalog.edge_ne,
217+
LEFTARG = edge,
218+
RIGHTARG = edge,
219+
COMMUTATOR = <>,
220+
NEGATOR = =,
221+
RESTRICT = neqsel,
222+
JOIN = neqjoinsel
223+
);
224+
225+
--
226+
-- Drop and recreate _label_name with new return type (cstring -> agtype)
227+
--
228+
DROP FUNCTION IF EXISTS ag_catalog._label_name(oid, graphid);
229+
230+
CREATE FUNCTION ag_catalog._label_name(graph_oid oid, graphid)
231+
RETURNS agtype
232+
LANGUAGE c
233+
IMMUTABLE
234+
PARALLEL SAFE
235+
AS 'MODULE_PATHNAME';
236+
237+
--
238+
-- Drop and recreate _agtype_build_vertex with new signature (cstring -> agtype for label)
239+
--
240+
DROP FUNCTION IF EXISTS ag_catalog._agtype_build_vertex(graphid, cstring, agtype);
241+
242+
CREATE FUNCTION ag_catalog._agtype_build_vertex(graphid, agtype, agtype)
243+
RETURNS agtype
244+
LANGUAGE c
245+
IMMUTABLE
246+
CALLED ON NULL INPUT
247+
PARALLEL SAFE
248+
AS 'MODULE_PATHNAME';
249+
250+
--
251+
-- Drop and recreate _agtype_build_edge with new signature (cstring -> agtype for label)
252+
--
253+
DROP FUNCTION IF EXISTS ag_catalog._agtype_build_edge(graphid, graphid, graphid, cstring, agtype);
254+
255+
CREATE FUNCTION ag_catalog._agtype_build_edge(graphid, graphid, graphid,
256+
agtype, agtype)
257+
RETURNS agtype
258+
LANGUAGE c
259+
IMMUTABLE
260+
CALLED ON NULL INPUT
261+
PARALLEL SAFE
262+
AS 'MODULE_PATHNAME';
263+
264+
--
265+
-- Helper function for optimized startNode/endNode
266+
--
267+
CREATE FUNCTION ag_catalog._get_vertex_by_graphid(text, graphid)
268+
RETURNS agtype
269+
LANGUAGE c
270+
STABLE
271+
RETURNS NULL ON NULL INPUT
272+
PARALLEL SAFE
273+
AS 'MODULE_PATHNAME';

0 commit comments

Comments
 (0)