Skip to content

Commit 3d7a428

Browse files
authored
Optmize vertex and edge builder functions (#1310)
Changes: - Added the agtype_raw module, which contains helper functions to build agtype directly without building an agtype_value first - Optimize _agtype_build_vertex and _agtype_build_edge functions The agtype_raw module: Inserting a composite agtype (i.e. object) into another agtype (i.e. as an array element) requires the first agtype to be deserialized into agtype_value. Then, the agtype_value to be serialized back into the second agtype. This module provides functions that can perform such insertion without deserializing first. It is meant to speed up queries that does deserialization-serialization back and forth involving deeply nested agtype objects.
1 parent e99aa6b commit 3d7a428

File tree

4 files changed

+353
-77
lines changed

4 files changed

+353
-77
lines changed

Diff for: Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ OBJS = src/backend/age.o \
5656
src/backend/utils/adt/agtype_ops.o \
5757
src/backend/utils/adt/agtype_parser.o \
5858
src/backend/utils/adt/agtype_util.o \
59+
src/backend/utils/adt/agtype_raw.o \
5960
src/backend/utils/adt/age_global_graph.o \
6061
src/backend/utils/adt/age_session_info.o \
6162
src/backend/utils/adt/age_vle.o \

Diff for: src/backend/utils/adt/agtype.c

+55-77
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
#include "utils/agtype.h"
5858
#include "utils/agtype_parser.h"
5959
#include "utils/ag_float8_supp.h"
60+
#include "utils/agtype_raw.h"
6061
#include "catalog/ag_graph.h"
6162
#include "catalog/ag_label.h"
6263
#include "utils/graphid.h"
@@ -2164,74 +2165,64 @@ PG_FUNCTION_INFO_V1(_agtype_build_vertex);
21642165
*/
21652166
Datum _agtype_build_vertex(PG_FUNCTION_ARGS)
21662167
{
2167-
agtype_in_state result;
21682168
graphid id;
2169+
char *label;
2170+
agtype *properties;
2171+
agtype_build_state *bstate;
2172+
agtype *rawscalar;
2173+
agtype *vertex;
21692174

2170-
memset(&result, 0, sizeof(agtype_in_state));
2171-
2172-
result.res = push_agtype_value(&result.parse_state, WAGT_BEGIN_OBJECT,
2173-
NULL);
2174-
2175-
/* process graphid */
2176-
result.res = push_agtype_value(&result.parse_state, WAGT_KEY,
2177-
string_to_agtype_value("id"));
2178-
2175+
/* handles null */
21792176
if (fcinfo->argnull[0])
21802177
{
21812178
ereport(ERROR,
21822179
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
21832180
errmsg("_agtype_build_vertex() graphid cannot be NULL")));
21842181
}
21852182

2186-
id = AG_GETARG_GRAPHID(0);
2187-
result.res = push_agtype_value(&result.parse_state, WAGT_VALUE,
2188-
integer_to_agtype_value(id));
2189-
2190-
/* process label */
2191-
result.res = push_agtype_value(&result.parse_state, WAGT_KEY,
2192-
string_to_agtype_value("label"));
2193-
21942183
if (fcinfo->argnull[1])
21952184
{
21962185
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
21972186
errmsg("_agtype_build_vertex() label cannot be NULL")));
21982187
}
21992188

2200-
result.res =
2201-
push_agtype_value(&result.parse_state, WAGT_VALUE,
2202-
string_to_agtype_value(PG_GETARG_CSTRING(1)));
2203-
2204-
/* process properties */
2205-
result.res = push_agtype_value(&result.parse_state, WAGT_KEY,
2206-
string_to_agtype_value("properties"));
2189+
id = AG_GETARG_GRAPHID(0);
2190+
label = PG_GETARG_CSTRING(1);
22072191

2208-
//if the properties object is null, push an empty object
22092192
if (fcinfo->argnull[2])
22102193
{
2211-
result.res = push_agtype_value(&result.parse_state, WAGT_BEGIN_OBJECT,
2212-
NULL);
2213-
result.res = push_agtype_value(&result.parse_state, WAGT_END_OBJECT,
2214-
NULL);
2194+
agtype_build_state *bstate = init_agtype_build_state(0, AGT_FOBJECT);
2195+
properties = build_agtype(bstate);
2196+
pfree_agtype_build_state(bstate);
22152197
}
22162198
else
22172199
{
2218-
agtype *properties = AG_GET_ARG_AGTYPE_P(2);
2200+
properties = AG_GET_ARG_AGTYPE_P(2);
22192201

22202202
if (!AGT_ROOT_IS_OBJECT(properties))
22212203
{
22222204
ereport(ERROR,
22232205
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
22242206
errmsg("_agtype_build_vertex() properties argument must be an object")));
22252207
}
2226-
2227-
add_agtype((Datum)properties, false, &result, AGTYPEOID, false);
22282208
}
22292209

2230-
result.res = push_agtype_value(&result.parse_state, WAGT_END_OBJECT, NULL);
2210+
bstate = init_agtype_build_state(3, AGT_FOBJECT);
2211+
write_string(bstate, "id");
2212+
write_string(bstate, "label");
2213+
write_string(bstate, "properties");
2214+
write_graphid(bstate, id);
2215+
write_string(bstate, label);
2216+
write_container(bstate, properties);
2217+
vertex = build_agtype(bstate);
2218+
pfree_agtype_build_state(bstate);
22312219

2232-
result.res->type = AGTV_VERTEX;
2220+
bstate = init_agtype_build_state(1, AGT_FARRAY | AGT_FSCALAR);
2221+
write_extended(bstate, vertex, AGT_HEADER_VERTEX);
2222+
rawscalar = build_agtype(bstate);
2223+
pfree_agtype_build_state(bstate);
22332224

2234-
PG_RETURN_POINTER(agtype_value_to_agtype(result.res));
2225+
PG_RETURN_POINTER(rawscalar);
22352226
}
22362227

22372228
Datum make_vertex(Datum id, Datum label, Datum properties)
@@ -2246,18 +2237,13 @@ PG_FUNCTION_INFO_V1(_agtype_build_edge);
22462237
*/
22472238
Datum _agtype_build_edge(PG_FUNCTION_ARGS)
22482239
{
2249-
agtype_in_state result;
2240+
agtype_build_state *bstate;
2241+
agtype *edge, *rawscalar;
22502242
graphid id, start_id, end_id;
2251-
2252-
memset(&result, 0, sizeof(agtype_in_state));
2253-
2254-
result.res = push_agtype_value(&result.parse_state, WAGT_BEGIN_OBJECT,
2255-
NULL);
2243+
char *label;
2244+
agtype *properties;
22562245

22572246
/* process graph id */
2258-
result.res = push_agtype_value(&result.parse_state, WAGT_KEY,
2259-
string_to_agtype_value("id"));
2260-
22612247
if (fcinfo->argnull[0])
22622248
{
22632249
ereport(ERROR,
@@ -2266,27 +2252,17 @@ Datum _agtype_build_edge(PG_FUNCTION_ARGS)
22662252
}
22672253

22682254
id = AG_GETARG_GRAPHID(0);
2269-
result.res = push_agtype_value(&result.parse_state, WAGT_VALUE,
2270-
integer_to_agtype_value(id));
22712255

22722256
/* process label */
2273-
result.res = push_agtype_value(&result.parse_state, WAGT_KEY,
2274-
string_to_agtype_value("label"));
2275-
22762257
if (fcinfo->argnull[3])
22772258
{
22782259
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
22792260
errmsg("_agtype_build_vertex() label cannot be NULL")));
22802261
}
22812262

2282-
result.res =
2283-
push_agtype_value(&result.parse_state, WAGT_VALUE,
2284-
string_to_agtype_value(PG_GETARG_CSTRING(3)));
2263+
label = PG_GETARG_CSTRING(3);
22852264

22862265
/* process end_id */
2287-
result.res = push_agtype_value(&result.parse_state, WAGT_KEY,
2288-
string_to_agtype_value("end_id"));
2289-
22902266
if (fcinfo->argnull[2])
22912267
{
22922268
ereport(ERROR,
@@ -2295,13 +2271,8 @@ Datum _agtype_build_edge(PG_FUNCTION_ARGS)
22952271
}
22962272

22972273
end_id = AG_GETARG_GRAPHID(2);
2298-
result.res = push_agtype_value(&result.parse_state, WAGT_VALUE,
2299-
integer_to_agtype_value(end_id));
23002274

23012275
/* process start_id */
2302-
result.res = push_agtype_value(&result.parse_state, WAGT_KEY,
2303-
string_to_agtype_value("start_id"));
2304-
23052276
if (fcinfo->argnull[1])
23062277
{
23072278
ereport(ERROR,
@@ -2310,40 +2281,47 @@ Datum _agtype_build_edge(PG_FUNCTION_ARGS)
23102281
}
23112282

23122283
start_id = AG_GETARG_GRAPHID(1);
2313-
result.res = push_agtype_value(&result.parse_state, WAGT_VALUE,
2314-
integer_to_agtype_value(start_id));
23152284

23162285
/* process properties */
2317-
result.res = push_agtype_value(&result.parse_state, WAGT_KEY,
2318-
string_to_agtype_value("properties"));
23192286

23202287
/* if the properties object is null, push an empty object */
23212288
if (fcinfo->argnull[4])
23222289
{
2323-
result.res = push_agtype_value(&result.parse_state, WAGT_BEGIN_OBJECT,
2324-
NULL);
2325-
result.res = push_agtype_value(&result.parse_state, WAGT_END_OBJECT,
2326-
NULL);
2290+
agtype_build_state *bstate = init_agtype_build_state(0, AGT_FOBJECT);
2291+
properties = build_agtype(bstate);
2292+
pfree_agtype_build_state(bstate);
23272293
}
23282294
else
23292295
{
2330-
agtype *properties = AG_GET_ARG_AGTYPE_P(4);
2296+
properties = AG_GET_ARG_AGTYPE_P(4);
23312297

23322298
if (!AGT_ROOT_IS_OBJECT(properties))
23332299
{
23342300
ereport(ERROR,
23352301
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
23362302
errmsg("_agtype_build_edge() properties argument must be an object")));
23372303
}
2338-
2339-
add_agtype((Datum)properties, false, &result, AGTYPEOID, false);
23402304
}
23412305

2342-
result.res = push_agtype_value(&result.parse_state, WAGT_END_OBJECT, NULL);
2343-
2344-
result.res->type = AGTV_EDGE;
2345-
2346-
PG_RETURN_POINTER(agtype_value_to_agtype(result.res));
2306+
bstate = init_agtype_build_state(5, AGT_FOBJECT);
2307+
write_string(bstate, "id");
2308+
write_string(bstate, "label");
2309+
write_string(bstate, "end_id");
2310+
write_string(bstate, "start_id");
2311+
write_string(bstate, "properties");
2312+
write_graphid(bstate, id);
2313+
write_string(bstate, label);
2314+
write_graphid(bstate, end_id);
2315+
write_graphid(bstate, start_id);
2316+
write_container(bstate, properties);
2317+
edge = build_agtype(bstate);
2318+
pfree_agtype_build_state(bstate);
2319+
2320+
bstate = init_agtype_build_state(1, AGT_FARRAY | AGT_FSCALAR);
2321+
write_extended(bstate, edge, AGT_HEADER_EDGE);
2322+
rawscalar = build_agtype(bstate);
2323+
pfree_agtype_build_state(bstate);
2324+
PG_RETURN_POINTER(rawscalar);
23472325
}
23482326

23492327
Datum make_edge(Datum id, Datum startid, Datum endid, Datum label,

0 commit comments

Comments
 (0)