Skip to content

Commit d351587

Browse files
committed
Update age_load to make property value conversion optional (apache#1525)
This is an addition to a previous patch that introduced loading property values from CSV files as agtype. This behavior is made optional in this patch with a boolean function parameter `load_as_agtype`. When this parameter is false, values are loaded as string.
1 parent cf1ce46 commit d351587

File tree

9 files changed

+120
-32
lines changed

9 files changed

+120
-32
lines changed

regress/expected/age_load.out

+49-9
Original file line numberDiff line numberDiff line change
@@ -243,20 +243,21 @@ NOTICE: graph "agload_conversion" has been created
243243

244244
(1 row)
245245

246+
-- vertex: load as agtype
246247
SELECT create_vlabel('agload_conversion','Person1');
247248
NOTICE: VLabel "Person1" has been created
248249
create_vlabel
249250
---------------
250251

251252
(1 row)
252253

253-
SELECT load_labels_from_file('agload_conversion', 'Person1', 'age_load/conversion_vertices.csv');
254+
SELECT load_labels_from_file('agload_conversion', 'Person1', 'age_load/conversion_vertices.csv', true, true);
254255
load_labels_from_file
255256
-----------------------
256257

257258
(1 row)
258259

259-
SELECT * FROM cypher('agload_conversion', $$ MATCH (n) RETURN properties(n) $$) as (a agtype);
260+
SELECT * FROM cypher('agload_conversion', $$ MATCH (n:Person1) RETURN properties(n) $$) as (a agtype);
260261
a
261262
------------------------------------------------------------------------------------
262263
{"id": 1, "bool": true, "__id__": 1, "string": "John Smith", "numeric": 1}
@@ -267,33 +268,46 @@ SELECT * FROM cypher('agload_conversion', $$ MATCH (n) RETURN properties(n) $$)
267268
{"id": 6, "bool": false, "__id__": 6, "string": "nUll", "numeric": 3.14}
268269
(6 rows)
269270

271+
-- vertex: load as string
270272
SELECT create_vlabel('agload_conversion','Person2');
271273
NOTICE: VLabel "Person2" has been created
272274
create_vlabel
273275
---------------
274276

275277
(1 row)
276278

277-
SELECT load_labels_from_file('agload_conversion', 'Person2', 'age_load/conversion_vertices.csv');
279+
SELECT load_labels_from_file('agload_conversion', 'Person2', 'age_load/conversion_vertices.csv', true, false);
278280
load_labels_from_file
279281
-----------------------
280282

281283
(1 row)
282284

283-
SELECT create_elabel('agload_conversion','Edges');
284-
NOTICE: ELabel "Edges" has been created
285+
SELECT * FROM cypher('agload_conversion', $$ MATCH (n:Person2) RETURN properties(n) $$) as (a agtype);
286+
a
287+
-------------------------------------------------------------------------------------
288+
{"id": "1", "bool": "true", "__id__": 1, "string": "John Smith", "numeric": "1"}
289+
{"id": "2", "bool": "false", "__id__": 2, "string": "John", "numeric": "-2"}
290+
{"id": "3", "bool": "true", "__id__": 3, "string": "John Smith", "numeric": "1.4"}
291+
{"id": "4", "bool": "false", "__id__": 4, "string": "\"John\"", "numeric": "-1e10"}
292+
{"id": "5", "bool": "false", "__id__": 5, "string": "null", "numeric": "0"}
293+
{"id": "6", "bool": "false", "__id__": 6, "string": "nUll", "numeric": "3.14"}
294+
(6 rows)
295+
296+
-- edge: load as agtype
297+
SELECT create_elabel('agload_conversion','Edges1');
298+
NOTICE: ELabel "Edges1" has been created
285299
create_elabel
286300
---------------
287301

288302
(1 row)
289303

290-
SELECT load_edges_from_file('agload_conversion', 'Edges', 'age_load/conversion_edges.csv');
304+
SELECT load_edges_from_file('agload_conversion', 'Edges1', 'age_load/conversion_edges.csv', true);
291305
load_edges_from_file
292306
----------------------
293307

294308
(1 row)
295309

296-
SELECT * FROM cypher('agload_conversion', $$ MATCH ()-[e]->() RETURN properties(e) $$) as (a agtype);
310+
SELECT * FROM cypher('agload_conversion', $$ MATCH ()-[e:Edges1]->() RETURN properties(e) $$) as (a agtype);
297311
a
298312
--------------------------------------------------------------
299313
{"bool": true, "string": "John Smith", "numeric": 1}
@@ -304,13 +318,39 @@ SELECT * FROM cypher('agload_conversion', $$ MATCH ()-[e]->() RETURN properties(
304318
{"bool": false, "string": "nUll", "numeric": 3.14}
305319
(6 rows)
306320

321+
-- edge: load as string
322+
SELECT create_elabel('agload_conversion','Edges2');
323+
NOTICE: ELabel "Edges2" has been created
324+
create_elabel
325+
---------------
326+
327+
(1 row)
328+
329+
SELECT load_edges_from_file('agload_conversion', 'Edges2', 'age_load/conversion_edges.csv', false);
330+
load_edges_from_file
331+
----------------------
332+
333+
(1 row)
334+
335+
SELECT * FROM cypher('agload_conversion', $$ MATCH ()-[e:Edges2]->() RETURN properties(e) $$) as (a agtype);
336+
a
337+
-------------------------------------------------------------
338+
{"bool": "true", "string": "John Smith", "numeric": "1"}
339+
{"bool": "false", "string": "John", "numeric": "-2"}
340+
{"bool": "true", "string": "John Smith", "numeric": "1.4"}
341+
{"bool": "false", "string": "\"John\"", "numeric": "-1e10"}
342+
{"bool": "false", "string": "null", "numeric": "0"}
343+
{"bool": "false", "string": "nUll", "numeric": "3.14"}
344+
(6 rows)
345+
307346
SELECT drop_graph('agload_conversion', true);
308-
NOTICE: drop cascades to 5 other objects
347+
NOTICE: drop cascades to 6 other objects
309348
DETAIL: drop cascades to table agload_conversion._ag_label_vertex
310349
drop cascades to table agload_conversion._ag_label_edge
311350
drop cascades to table agload_conversion."Person1"
312351
drop cascades to table agload_conversion."Person2"
313-
drop cascades to table agload_conversion."Edges"
352+
drop cascades to table agload_conversion."Edges1"
353+
drop cascades to table agload_conversion."Edges2"
314354
NOTICE: graph "agload_conversion" has been dropped
315355
drop_graph
316356
------------

regress/sql/age_load.sql

+16-7
Original file line numberDiff line numberDiff line change
@@ -85,15 +85,24 @@ SELECT drop_graph('agload_test_graph', true);
8585
--
8686
SELECT create_graph('agload_conversion');
8787

88+
-- vertex: load as agtype
8889
SELECT create_vlabel('agload_conversion','Person1');
89-
SELECT load_labels_from_file('agload_conversion', 'Person1', 'age_load/conversion_vertices.csv');
90-
SELECT * FROM cypher('agload_conversion', $$ MATCH (n) RETURN properties(n) $$) as (a agtype);
90+
SELECT load_labels_from_file('agload_conversion', 'Person1', 'age_load/conversion_vertices.csv', true, true);
91+
SELECT * FROM cypher('agload_conversion', $$ MATCH (n:Person1) RETURN properties(n) $$) as (a agtype);
9192

93+
-- vertex: load as string
9294
SELECT create_vlabel('agload_conversion','Person2');
93-
SELECT load_labels_from_file('agload_conversion', 'Person2', 'age_load/conversion_vertices.csv');
94-
95-
SELECT create_elabel('agload_conversion','Edges');
96-
SELECT load_edges_from_file('agload_conversion', 'Edges', 'age_load/conversion_edges.csv');
97-
SELECT * FROM cypher('agload_conversion', $$ MATCH ()-[e]->() RETURN properties(e) $$) as (a agtype);
95+
SELECT load_labels_from_file('agload_conversion', 'Person2', 'age_load/conversion_vertices.csv', true, false);
96+
SELECT * FROM cypher('agload_conversion', $$ MATCH (n:Person2) RETURN properties(n) $$) as (a agtype);
97+
98+
-- edge: load as agtype
99+
SELECT create_elabel('agload_conversion','Edges1');
100+
SELECT load_edges_from_file('agload_conversion', 'Edges1', 'age_load/conversion_edges.csv', true);
101+
SELECT * FROM cypher('agload_conversion', $$ MATCH ()-[e:Edges1]->() RETURN properties(e) $$) as (a agtype);
102+
103+
-- edge: load as string
104+
SELECT create_elabel('agload_conversion','Edges2');
105+
SELECT load_edges_from_file('agload_conversion', 'Edges2', 'age_load/conversion_edges.csv', false);
106+
SELECT * FROM cypher('agload_conversion', $$ MATCH ()-[e:Edges2]->() RETURN properties(e) $$) as (a agtype);
98107

99108
SELECT drop_graph('agload_conversion', true);

sql/age_main.sql

+8-2
Original file line numberDiff line numberDiff line change
@@ -122,17 +122,23 @@ CREATE FUNCTION ag_catalog.drop_label(graph_name name, label_name name,
122122
LANGUAGE c
123123
AS 'MODULE_PATHNAME';
124124

125+
--
126+
-- If `load_as_agtype` is true, property values are loaded as agtype; otherwise
127+
-- loaded as string.
128+
--
125129
CREATE FUNCTION ag_catalog.load_labels_from_file(graph_name name,
126130
label_name name,
127131
file_path text,
128-
id_field_exists bool default true)
132+
id_field_exists bool default true,
133+
load_as_agtype bool default false)
129134
RETURNS void
130135
LANGUAGE c
131136
AS 'MODULE_PATHNAME';
132137

133138
CREATE FUNCTION ag_catalog.load_edges_from_file(graph_name name,
134139
label_name name,
135-
file_path text)
140+
file_path text,
141+
load_as_agtype bool default false)
136142
RETURNS void
137143
LANGUAGE c
138144
AS 'MODULE_PATHNAME';

src/backend/utils/load/ag_load_edges.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ void edge_row_cb(int delim __attribute__((unused)), void *data)
100100
end_vertex_graph_id = make_graphid(end_vertex_type_id, end_id_int);
101101

102102
props = create_agtype_from_list_i(cr->header, cr->fields,
103-
n_fields, 4);
103+
n_fields, 4, cr->load_as_agtype);
104104

105105
insert_edge_simple(cr->graph_oid, cr->object_name,
106106
object_graph_id, start_vertex_graph_id,
@@ -153,7 +153,8 @@ int create_edges_from_csv_file(char *file_path,
153153
char *graph_name,
154154
Oid graph_oid,
155155
char *object_name,
156-
int object_id )
156+
int object_id,
157+
bool load_as_agtype)
157158
{
158159

159160
FILE *fp;
@@ -190,6 +191,7 @@ int create_edges_from_csv_file(char *file_path,
190191
cr.graph_oid = graph_oid;
191192
cr.object_name = object_name;
192193
cr.object_id = object_id;
194+
cr.load_as_agtype = load_as_agtype;
193195

194196
while ((bytes_read=fread(buf, 1, 1024, fp)) > 0)
195197
{

src/backend/utils/load/ag_load_labels.c

+5-2
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ void vertex_row_cb(int delim __attribute__((unused)), void *data)
9292
object_graph_id = make_graphid(cr->object_id, label_id_int);
9393

9494
props = create_agtype_from_list(cr->header, cr->fields,
95-
n_fields, label_id_int);
95+
n_fields, label_id_int,
96+
cr->load_as_agtype);
9697
insert_vertex_simple(cr->graph_oid, cr->object_name,
9798
object_graph_id, props);
9899
pfree(props);
@@ -145,7 +146,8 @@ int create_labels_from_csv_file(char *file_path,
145146
Oid graph_oid,
146147
char *object_name,
147148
int object_id,
148-
bool id_field_exists)
149+
bool id_field_exists,
150+
bool load_as_agtype)
149151
{
150152

151153
FILE *fp;
@@ -184,6 +186,7 @@ int create_labels_from_csv_file(char *file_path,
184186
cr.object_name = object_name;
185187
cr.object_id = object_id;
186188
cr.id_field_exists = id_field_exists;
189+
cr.load_as_agtype = load_as_agtype;
187190

188191

189192

src/backend/utils/load/age_load.c

+29-6
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ static agtype_value *csv_value_to_agtype_value(char *csv_val)
8888
}
8989

9090
agtype *create_agtype_from_list(char **header, char **fields, size_t fields_len,
91-
int64 vertex_id)
91+
int64 vertex_id, bool load_as_agtype)
9292
{
9393
agtype* out;
9494
agtype_value* key_agtype;
@@ -121,7 +121,15 @@ agtype *create_agtype_from_list(char **header, char **fields, size_t fields_len,
121121
WAGT_KEY,
122122
key_agtype);
123123

124-
value_agtype = csv_value_to_agtype_value(fields[i]);
124+
if (load_as_agtype)
125+
{
126+
value_agtype = csv_value_to_agtype_value(fields[i]);
127+
}
128+
else
129+
{
130+
value_agtype = string_to_agtype_value(fields[i]);
131+
}
132+
125133
result.res = push_agtype_value(&result.parse_state,
126134
WAGT_VALUE,
127135
value_agtype);
@@ -140,7 +148,8 @@ agtype *create_agtype_from_list(char **header, char **fields, size_t fields_len,
140148
}
141149

142150
agtype* create_agtype_from_list_i(char **header, char **fields,
143-
size_t fields_len, size_t start_index)
151+
size_t fields_len, size_t start_index,
152+
bool load_as_agtype)
144153
{
145154
agtype* out;
146155
agtype_value* key_agtype;
@@ -164,7 +173,16 @@ agtype* create_agtype_from_list_i(char **header, char **fields,
164173
result.res = push_agtype_value(&result.parse_state,
165174
WAGT_KEY,
166175
key_agtype);
167-
value_agtype = csv_value_to_agtype_value(fields[i]);
176+
177+
if (load_as_agtype)
178+
{
179+
value_agtype = csv_value_to_agtype_value(fields[i]);
180+
}
181+
else
182+
{
183+
value_agtype = string_to_agtype_value(fields[i]);
184+
}
185+
168186
result.res = push_agtype_value(&result.parse_state,
169187
WAGT_VALUE,
170188
value_agtype);
@@ -256,6 +274,7 @@ Datum load_labels_from_file(PG_FUNCTION_ARGS)
256274
Oid graph_oid;
257275
int32 label_id;
258276
bool id_field_exists;
277+
bool load_as_agtype;
259278

260279
if (PG_ARGISNULL(0))
261280
{
@@ -279,6 +298,7 @@ Datum load_labels_from_file(PG_FUNCTION_ARGS)
279298
label_name = PG_GETARG_NAME(1);
280299
file_path = PG_GETARG_TEXT_P(2);
281300
id_field_exists = PG_GETARG_BOOL(3);
301+
load_as_agtype = PG_GETARG_BOOL(4);
282302

283303

284304
graph_name_str = NameStr(*graph_name);
@@ -289,7 +309,8 @@ Datum load_labels_from_file(PG_FUNCTION_ARGS)
289309
label_id = get_label_id(label_name_str, graph_oid);
290310

291311
create_labels_from_csv_file(file_path_str, graph_name_str, graph_oid,
292-
label_name_str, label_id, id_field_exists);
312+
label_name_str, label_id, id_field_exists,
313+
load_as_agtype);
293314
PG_RETURN_VOID();
294315

295316
}
@@ -306,6 +327,7 @@ Datum load_edges_from_file(PG_FUNCTION_ARGS)
306327
char* file_path_str;
307328
Oid graph_oid;
308329
int32 label_id;
330+
bool load_as_agtype;
309331

310332
if (PG_ARGISNULL(0))
311333
{
@@ -328,6 +350,7 @@ Datum load_edges_from_file(PG_FUNCTION_ARGS)
328350
graph_name = PG_GETARG_NAME(0);
329351
label_name = PG_GETARG_NAME(1);
330352
file_path = PG_GETARG_TEXT_P(2);
353+
load_as_agtype = PG_GETARG_BOOL(3);
331354

332355
graph_name_str = NameStr(*graph_name);
333356
label_name_str = NameStr(*label_name);
@@ -337,7 +360,7 @@ Datum load_edges_from_file(PG_FUNCTION_ARGS)
337360
label_id = get_label_id(label_name_str, graph_oid);
338361

339362
create_edges_from_csv_file(file_path_str, graph_name_str, graph_oid,
340-
label_name_str, label_id);
363+
label_name_str, label_id, load_as_agtype);
341364
PG_RETURN_VOID();
342365

343366
}

src/include/utils/load/ag_load_edges.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ typedef struct {
3838
int object_id;
3939
char *start_vertex;
4040
char *end_vertex;
41+
bool load_as_agtype;
4142

4243
} csv_edge_reader;
4344

@@ -46,7 +47,8 @@ void edge_field_cb(void *field, size_t field_len, void *data);
4647
void edge_row_cb(int delim __attribute__((unused)), void *data);
4748

4849
int create_edges_from_csv_file(char *file_path, char *graph_name, Oid graph_oid,
49-
char *object_name, int object_id );
50+
char *object_name, int object_id,
51+
bool load_as_agtype);
5052

5153
#endif /* AG_LOAD_EDGES_H */
5254

src/include/utils/load/ag_load_labels.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ typedef struct {
5050
char *object_name;
5151
int object_id;
5252
bool id_field_exists;
53+
bool load_as_agtype;
5354
} csv_vertex_reader;
5455

5556

@@ -58,6 +59,6 @@ void vertex_row_cb(int delim __attribute__((unused)), void *data);
5859

5960
int create_labels_from_csv_file(char *file_path, char *graph_name, Oid graph_oid,
6061
char *object_name, int object_id,
61-
bool id_field_exists);
62+
bool id_field_exists, bool load_as_agtype);
6263

6364
#endif /* AG_LOAD_LABELS_H */

src/include/utils/load/age_load.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,11 @@
3232
agtype* create_empty_agtype(void);
3333

3434
agtype* create_agtype_from_list(char **header, char **fields,
35-
size_t fields_len, int64 vertex_id);
35+
size_t fields_len, int64 vertex_id,
36+
bool load_as_agtype);
3637
agtype* create_agtype_from_list_i(char **header, char **fields,
37-
size_t fields_len, size_t start_index);
38+
size_t fields_len, size_t start_index,
39+
bool load_as_agtype);
3840
void insert_vertex_simple(Oid graph_oid, char *label_name, graphid vertex_id,
3941
agtype *vertex_properties);
4042
void insert_edge_simple(Oid graph_oid, char *label_name, graphid edge_id,

0 commit comments

Comments
 (0)