Add example write procedure (#244)
This commit is contained in:
parent
721eefe263
commit
e33fa5f9c0
@ -720,6 +720,7 @@ enum mgp_error mgp_graph_get_vertex_by_id(struct mgp_graph *g, struct mgp_vertex
|
||||
enum mgp_error mgp_graph_is_mutable(struct mgp_graph *graph, int *result);
|
||||
|
||||
/// Add a new vertex to the graph.
|
||||
/// Resulting vertex must be freed using mgp_vertex_destroy.
|
||||
/// Return MGP_ERROR_IMMUTABLE_OBJECT if `graph` is immutable.
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate a mgp_vertex.
|
||||
enum mgp_error mgp_graph_create_vertex(struct mgp_graph *graph, struct mgp_memory *memory, struct mgp_vertex **result);
|
||||
@ -736,7 +737,7 @@ enum mgp_error mgp_graph_delete_vertex(struct mgp_graph *graph, struct mgp_verte
|
||||
enum mgp_error mgp_graph_detach_delete_vertex(struct mgp_graph *graph, struct mgp_vertex *vertex);
|
||||
|
||||
/// Add a new directed edge between the two vertices with the specified label.
|
||||
/// NULL is returned if the the edge creation fails for any reason.
|
||||
/// Resulting edge must be freed using mgp_edge_destroy.
|
||||
/// Return MGP_ERROR_IMMUTABLE_OBJECT if `graph` is immutable.
|
||||
/// Return MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate a mgp_edge.
|
||||
/// Return MGP_ERROR_DELETED_OBJECT if `from` or `to` has been deleted.
|
||||
|
@ -65,18 +65,11 @@ static void procedure(struct mgp_list *args, struct mgp_graph *graph, struct mgp
|
||||
error_free_list:
|
||||
mgp_list_destroy(args_copy);
|
||||
error_something_went_wrong:
|
||||
// Best effort. If it fails, there is nothing we can do.
|
||||
mgp_result_set_error_msg(result, "Something went wrong!");
|
||||
return;
|
||||
}
|
||||
|
||||
static void write_procedure(struct mgp_list *args, struct mgp_graph *graph, struct mgp_result *result,
|
||||
struct mgp_memory *memory) {
|
||||
// TODO(antaljanosbenjamin): Finish this example
|
||||
}
|
||||
|
||||
// Each module needs to define mgp_init_module function.
|
||||
// Here you can register multiple procedures your module supports.
|
||||
int mgp_init_module(struct mgp_module *module, struct mgp_memory *memory) {
|
||||
int add_read_procedure(struct mgp_module *module, struct mgp_memory *memory) {
|
||||
struct mgp_proc *proc = NULL;
|
||||
if (mgp_module_add_read_procedure(module, "procedure", procedure, &proc) != MGP_ERROR_NO_ERROR) {
|
||||
return 1;
|
||||
@ -119,6 +112,101 @@ int mgp_init_module(struct mgp_module *module, struct mgp_memory *memory) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This example procedure returns one field called `created_vertex`
|
||||
// which contains the newly created vertex.
|
||||
// In case of memory errors, this function will report them and finish
|
||||
// executing.
|
||||
//
|
||||
// The procedure can be invoked in openCypher using the following call:
|
||||
// CALL example.write_procedure("property value") YIELD created_vertex;
|
||||
static void write_procedure(struct mgp_list *args, struct mgp_graph *graph, struct mgp_result *result,
|
||||
struct mgp_memory *memory) {
|
||||
size_t args_size = 0;
|
||||
if (mgp_list_size(args, &args_size) != MGP_ERROR_NO_ERROR) {
|
||||
goto error_something_went_wrong;
|
||||
}
|
||||
if (args_size != 1) {
|
||||
mgp_result_set_error_msg(result, "The procedure requires exactly one argument!");
|
||||
return;
|
||||
}
|
||||
|
||||
struct mgp_value *arg = NULL;
|
||||
if (mgp_list_at(args, 0, &arg) != MGP_ERROR_NO_ERROR) {
|
||||
goto error_something_went_wrong;
|
||||
}
|
||||
|
||||
struct mgp_vertex *vertex = NULL;
|
||||
if (mgp_graph_create_vertex(graph, memory, &vertex) != MGP_ERROR_NO_ERROR) {
|
||||
goto error_something_went_wrong;
|
||||
}
|
||||
|
||||
if (mgp_vertex_set_property(vertex, "new_property", arg) != MGP_ERROR_NO_ERROR) {
|
||||
goto error_destroy_vertex;
|
||||
}
|
||||
|
||||
struct mgp_value *vertex_value = NULL;
|
||||
if (mgp_value_make_vertex(vertex, &vertex_value) != MGP_ERROR_NO_ERROR) {
|
||||
goto error_destroy_vertex;
|
||||
}
|
||||
|
||||
struct mgp_result_record *record = NULL;
|
||||
if (mgp_result_new_record(result, &record) != MGP_ERROR_NO_ERROR) {
|
||||
goto error_destroy_vertex_value;
|
||||
}
|
||||
|
||||
if (mgp_result_record_insert(record, "created_vertex", vertex_value) != MGP_ERROR_NO_ERROR) {
|
||||
goto error_destroy_vertex_value;
|
||||
}
|
||||
mgp_value_destroy(vertex_value);
|
||||
|
||||
return;
|
||||
|
||||
error_destroy_vertex:
|
||||
mgp_vertex_destroy(vertex);
|
||||
goto error_something_went_wrong;
|
||||
error_destroy_vertex_value:
|
||||
mgp_value_destroy(vertex_value);
|
||||
error_something_went_wrong:
|
||||
// Best effort. If it fails, there is nothing we can do.
|
||||
mgp_result_set_error_msg(result, "Something went wrong!");
|
||||
}
|
||||
|
||||
int add_write_procedure(struct mgp_module *module, struct mgp_memory *memory) {
|
||||
struct mgp_proc *proc = NULL;
|
||||
if (mgp_module_add_write_procedure(module, "write_procedure", write_procedure, &proc) != MGP_ERROR_NO_ERROR) {
|
||||
return 1;
|
||||
}
|
||||
struct mgp_type *string_type = NULL;
|
||||
if (mgp_type_string(&string_type) != MGP_ERROR_NO_ERROR) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (mgp_proc_add_arg(proc, "required_arg", string_type) != MGP_ERROR_NO_ERROR) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct mgp_type *node_type = NULL;
|
||||
if (mgp_type_node(&node_type) != MGP_ERROR_NO_ERROR) {
|
||||
return 1;
|
||||
}
|
||||
if (mgp_proc_add_result(proc, "created_vertex", node_type) != MGP_ERROR_NO_ERROR) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Each module needs to define mgp_init_module function.
|
||||
// Here you can register multiple procedures your module supports.
|
||||
int mgp_init_module(struct mgp_module *module, struct mgp_memory *memory) {
|
||||
if (add_read_procedure(module, memory) != 0) {
|
||||
return -1;
|
||||
}
|
||||
if (add_write_procedure(module, memory) != 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This is an optional function if you need to release any resources before the
|
||||
// module is unloaded. You will probably need this if you acquired some
|
||||
// resources in mgp_init_module.
|
||||
|
@ -14,7 +14,7 @@ def procedure(context: mgp.ProcCtx,
|
||||
vertex_count=int,
|
||||
avg_degree=mgp.Number,
|
||||
props=mgp.Nullable[mgp.Map]):
|
||||
'''
|
||||
"""
|
||||
This example procedure returns 4 fields.
|
||||
|
||||
* `args` is a copy of arguments passed to the procedure.
|
||||
@ -31,7 +31,7 @@ def procedure(context: mgp.ProcCtx,
|
||||
MATCH (n) CALL example.procedure(n, 1) YIELD * RETURN *;
|
||||
|
||||
Naturally, you may pass in different arguments or yield different fields.
|
||||
'''
|
||||
"""
|
||||
# Create a properties map if we received an Edge, Vertex, or Path instance.
|
||||
props = None
|
||||
if isinstance(required_arg, (mgp.Edge, mgp.Vertex)):
|
||||
@ -53,3 +53,40 @@ def procedure(context: mgp.ProcCtx,
|
||||
# Multiple rows can be produced by returning an iterable of mgp.Record.
|
||||
return mgp.Record(args=args_copy, vertex_count=vertex_count,
|
||||
avg_degree=avg_degree, props=props)
|
||||
|
||||
|
||||
@mgp.write_proc
|
||||
def write_procedure(context: mgp.ProcCtx, property_name: str, property_value: mgp.Nullable[mgp.Any]) -> mgp.Record(created_vertex=mgp.Vertex):
|
||||
"""
|
||||
This example procedure creates a new vertex with the specified property
|
||||
and connects it to all existing vertex which has the same property with
|
||||
the same name. It returns one field called `created_vertex` which
|
||||
contains the newly created vertex.
|
||||
|
||||
Any errors can be reported by raising an Exception.
|
||||
|
||||
The procedure can be invoked in openCypher using the following calls:
|
||||
- CALL example.write_procedure("property_name", "property_value")
|
||||
YIELD created_vertex;
|
||||
- MATCH (n) WHERE n.my_property IS NOT NULL
|
||||
WITH n.my_property as property_value
|
||||
CALL example.write_procedure("my_property", property_value)
|
||||
YIELD created_vertex;
|
||||
|
||||
Naturally, you may pass in different arguments.
|
||||
"""
|
||||
# Collect all the vertices that has the required property with the same
|
||||
# value
|
||||
vertices_to_connect = []
|
||||
for v in context.graph.vertices:
|
||||
if v.properties[property_name] == property_value:
|
||||
vertices_to_connect.append(v)
|
||||
# Create the new vertex and set its property
|
||||
vertex = context.graph.create_vertex()
|
||||
vertex.properties.set(property_name, property_value)
|
||||
# Connect the new vertex to the other vertices
|
||||
for v in vertices_to_connect:
|
||||
print("ALMA")
|
||||
context.graph.create_edge(vertex, v, mgp.EdgeType("HAS_SAME_VALUE"))
|
||||
|
||||
return mgp.Record(created_vertex=vertex)
|
||||
|
Loading…
Reference in New Issue
Block a user