Integrate loading openCypher module procedures
Summary:
All mgp_* symbols are exported from Memgraph executable, no other
symbols should be visible.
The primary C API header, mg_procedure.h, is now part of the
installation. Also, added a shippable query module example.
Directory `query_modules` is meant to contain sources of modules we
write and ship as part of the installation. Currently, there's only an
example module, but there may be potentially more. Some modules could
only be installed as part of the enterprise release.
For Memgraph to load custom procedures, it needs to be started with a
flag pointing to a directory with compiled shared libraries implementing
those procedures.
Reviewers: mferencevic, ipaljak, llugovic, dsantl, buda
Reviewed By: mferencevic
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D2538
2019-10-31 23:36:34 +08:00
|
|
|
// Compile with clang or gcc:
|
|
|
|
// clang -Wall -shared -fPIC -I <path-to-memgraph-include> example.c -o example.so
|
|
|
|
// <path-to-memgraph-include> for installed Memgraph will usually be something
|
|
|
|
// like `/usr/include/memgraph` or `/usr/local/include/memgraph`.
|
|
|
|
// To use the compiled module, you need to run Memgraph configured to load
|
|
|
|
// modules from the directory where the compiled module can be found.
|
|
|
|
#include "mg_procedure.h"
|
|
|
|
|
|
|
|
// This example procedure returns 2 fields: `args` and `result`.
|
|
|
|
// * `args` is a copy of arguments passed to the procedure.
|
|
|
|
// * `result` is the result of this procedure, a "Hello World!" string.
|
2019-11-14 22:54:10 +08:00
|
|
|
// In case of memory errors, this function will report them and finish
|
|
|
|
// executing.
|
Integrate loading openCypher module procedures
Summary:
All mgp_* symbols are exported from Memgraph executable, no other
symbols should be visible.
The primary C API header, mg_procedure.h, is now part of the
installation. Also, added a shippable query module example.
Directory `query_modules` is meant to contain sources of modules we
write and ship as part of the installation. Currently, there's only an
example module, but there may be potentially more. Some modules could
only be installed as part of the enterprise release.
For Memgraph to load custom procedures, it needs to be started with a
flag pointing to a directory with compiled shared libraries implementing
those procedures.
Reviewers: mferencevic, ipaljak, llugovic, dsantl, buda
Reviewed By: mferencevic
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D2538
2019-10-31 23:36:34 +08:00
|
|
|
//
|
2019-11-26 20:42:37 +08:00
|
|
|
// The procedure can be invoked in openCypher using the following calls:
|
|
|
|
// CALL example.procedure(1, 2) YIELD args, result;
|
|
|
|
// CALL example.procedure(1) YIELD args, result;
|
Integrate loading openCypher module procedures
Summary:
All mgp_* symbols are exported from Memgraph executable, no other
symbols should be visible.
The primary C API header, mg_procedure.h, is now part of the
installation. Also, added a shippable query module example.
Directory `query_modules` is meant to contain sources of modules we
write and ship as part of the installation. Currently, there's only an
example module, but there may be potentially more. Some modules could
only be installed as part of the enterprise release.
For Memgraph to load custom procedures, it needs to be started with a
flag pointing to a directory with compiled shared libraries implementing
those procedures.
Reviewers: mferencevic, ipaljak, llugovic, dsantl, buda
Reviewed By: mferencevic
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D2538
2019-10-31 23:36:34 +08:00
|
|
|
// Naturally, you may pass in different arguments or yield less fields.
|
2021-09-09 22:10:19 +08:00
|
|
|
static void procedure(struct mgp_list *args, struct mgp_graph *graph, struct mgp_result *result,
|
2019-11-14 22:54:10 +08:00
|
|
|
struct mgp_memory *memory) {
|
2021-09-09 16:44:47 +08:00
|
|
|
size_t args_size = 0;
|
|
|
|
if (mgp_list_size(args, &args_size) != MGP_ERROR_NO_ERROR) {
|
|
|
|
goto error_something_went_wrong;
|
|
|
|
}
|
|
|
|
struct mgp_list *args_copy = NULL;
|
|
|
|
if (mgp_list_make_empty(args_size, memory, &args_copy) != MGP_ERROR_NO_ERROR) {
|
|
|
|
goto error_something_went_wrong;
|
|
|
|
}
|
|
|
|
for (size_t i = 0; i < args_size; ++i) {
|
2021-09-09 22:10:19 +08:00
|
|
|
struct mgp_value *value = NULL;
|
2021-09-09 16:44:47 +08:00
|
|
|
if (mgp_list_at(args, i, &value) != MGP_ERROR_NO_ERROR) {
|
|
|
|
goto error_free_list;
|
|
|
|
}
|
|
|
|
if (mgp_list_append(args_copy, value) != MGP_ERROR_NO_ERROR) {
|
|
|
|
goto error_free_list;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
struct mgp_result_record *record = NULL;
|
|
|
|
if (mgp_result_new_record(result, &record) != MGP_ERROR_NO_ERROR) {
|
|
|
|
goto error_free_list;
|
|
|
|
}
|
Integrate loading openCypher module procedures
Summary:
All mgp_* symbols are exported from Memgraph executable, no other
symbols should be visible.
The primary C API header, mg_procedure.h, is now part of the
installation. Also, added a shippable query module example.
Directory `query_modules` is meant to contain sources of modules we
write and ship as part of the installation. Currently, there's only an
example module, but there may be potentially more. Some modules could
only be installed as part of the enterprise release.
For Memgraph to load custom procedures, it needs to be started with a
flag pointing to a directory with compiled shared libraries implementing
those procedures.
Reviewers: mferencevic, ipaljak, llugovic, dsantl, buda
Reviewed By: mferencevic
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D2538
2019-10-31 23:36:34 +08:00
|
|
|
// Transfer ownership of args_copy to mgp_value.
|
2021-09-09 16:44:47 +08:00
|
|
|
struct mgp_value *args_value = NULL;
|
|
|
|
if (mgp_value_make_list(args_copy, &args_value) != MGP_ERROR_NO_ERROR) {
|
|
|
|
goto error_free_list;
|
|
|
|
}
|
Integrate loading openCypher module procedures
Summary:
All mgp_* symbols are exported from Memgraph executable, no other
symbols should be visible.
The primary C API header, mg_procedure.h, is now part of the
installation. Also, added a shippable query module example.
Directory `query_modules` is meant to contain sources of modules we
write and ship as part of the installation. Currently, there's only an
example module, but there may be potentially more. Some modules could
only be installed as part of the enterprise release.
For Memgraph to load custom procedures, it needs to be started with a
flag pointing to a directory with compiled shared libraries implementing
those procedures.
Reviewers: mferencevic, ipaljak, llugovic, dsantl, buda
Reviewed By: mferencevic
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D2538
2019-10-31 23:36:34 +08:00
|
|
|
// Release `args_value` and contained `args_copy`.
|
2021-09-09 16:44:47 +08:00
|
|
|
if (mgp_result_record_insert(record, "args", args_value) != MGP_ERROR_NO_ERROR) {
|
|
|
|
mgp_value_destroy(args_value);
|
|
|
|
goto error_something_went_wrong;
|
|
|
|
}
|
Integrate loading openCypher module procedures
Summary:
All mgp_* symbols are exported from Memgraph executable, no other
symbols should be visible.
The primary C API header, mg_procedure.h, is now part of the
installation. Also, added a shippable query module example.
Directory `query_modules` is meant to contain sources of modules we
write and ship as part of the installation. Currently, there's only an
example module, but there may be potentially more. Some modules could
only be installed as part of the enterprise release.
For Memgraph to load custom procedures, it needs to be started with a
flag pointing to a directory with compiled shared libraries implementing
those procedures.
Reviewers: mferencevic, ipaljak, llugovic, dsantl, buda
Reviewed By: mferencevic
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D2538
2019-10-31 23:36:34 +08:00
|
|
|
mgp_value_destroy(args_value);
|
2021-09-09 16:44:47 +08:00
|
|
|
struct mgp_value *hello_world_value = NULL;
|
|
|
|
if (mgp_value_make_string("Hello World!", memory, &hello_world_value) != MGP_ERROR_NO_ERROR) {
|
|
|
|
goto error_something_went_wrong;
|
|
|
|
}
|
|
|
|
enum mgp_error insert_result = mgp_result_record_insert(record, "result", hello_world_value);
|
Integrate loading openCypher module procedures
Summary:
All mgp_* symbols are exported from Memgraph executable, no other
symbols should be visible.
The primary C API header, mg_procedure.h, is now part of the
installation. Also, added a shippable query module example.
Directory `query_modules` is meant to contain sources of modules we
write and ship as part of the installation. Currently, there's only an
example module, but there may be potentially more. Some modules could
only be installed as part of the enterprise release.
For Memgraph to load custom procedures, it needs to be started with a
flag pointing to a directory with compiled shared libraries implementing
those procedures.
Reviewers: mferencevic, ipaljak, llugovic, dsantl, buda
Reviewed By: mferencevic
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D2538
2019-10-31 23:36:34 +08:00
|
|
|
mgp_value_destroy(hello_world_value);
|
2021-09-09 16:44:47 +08:00
|
|
|
if (insert_result != MGP_ERROR_NO_ERROR) {
|
|
|
|
goto error_something_went_wrong;
|
|
|
|
}
|
Integrate loading openCypher module procedures
Summary:
All mgp_* symbols are exported from Memgraph executable, no other
symbols should be visible.
The primary C API header, mg_procedure.h, is now part of the
installation. Also, added a shippable query module example.
Directory `query_modules` is meant to contain sources of modules we
write and ship as part of the installation. Currently, there's only an
example module, but there may be potentially more. Some modules could
only be installed as part of the enterprise release.
For Memgraph to load custom procedures, it needs to be started with a
flag pointing to a directory with compiled shared libraries implementing
those procedures.
Reviewers: mferencevic, ipaljak, llugovic, dsantl, buda
Reviewed By: mferencevic
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D2538
2019-10-31 23:36:34 +08:00
|
|
|
// We have successfully finished, so return without error reporting.
|
|
|
|
return;
|
|
|
|
|
|
|
|
error_free_list:
|
|
|
|
mgp_list_destroy(args_copy);
|
2021-09-09 16:44:47 +08:00
|
|
|
error_something_went_wrong:
|
2021-10-02 01:33:46 +08:00
|
|
|
// Best effort. If it fails, there is nothing we can do.
|
2021-09-09 16:44:47 +08:00
|
|
|
mgp_result_set_error_msg(result, "Something went wrong!");
|
2021-09-09 22:10:19 +08:00
|
|
|
}
|
|
|
|
|
2021-10-02 01:33:46 +08:00
|
|
|
int add_read_procedure(struct mgp_module *module, struct mgp_memory *memory) {
|
2021-09-09 16:44:47 +08:00
|
|
|
struct mgp_proc *proc = NULL;
|
|
|
|
if (mgp_module_add_read_procedure(module, "procedure", procedure, &proc) != MGP_ERROR_NO_ERROR) {
|
|
|
|
return 1;
|
|
|
|
}
|
2021-09-09 22:10:19 +08:00
|
|
|
struct mgp_type *any_type = NULL;
|
2021-09-09 16:44:47 +08:00
|
|
|
if (mgp_type_any(&any_type) != MGP_ERROR_NO_ERROR) {
|
2019-11-14 22:54:10 +08:00
|
|
|
return 1;
|
2021-09-09 16:44:47 +08:00
|
|
|
}
|
2021-09-09 22:10:19 +08:00
|
|
|
struct mgp_type *nullable_any_type = NULL;
|
2021-09-09 16:44:47 +08:00
|
|
|
if (mgp_type_nullable(any_type, &nullable_any_type) != MGP_ERROR_NO_ERROR) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (mgp_proc_add_arg(proc, "required_arg", nullable_any_type) != MGP_ERROR_NO_ERROR) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct mgp_value *null_value = NULL;
|
|
|
|
if (mgp_value_make_null(memory, &null_value) != MGP_ERROR_NO_ERROR) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (mgp_proc_add_opt_arg(proc, "optional_arg", nullable_any_type, null_value) != MGP_ERROR_NO_ERROR) {
|
2019-11-14 22:54:10 +08:00
|
|
|
mgp_value_destroy(null_value);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
mgp_value_destroy(null_value);
|
2021-09-09 22:10:19 +08:00
|
|
|
struct mgp_type *string = NULL;
|
2021-09-09 16:44:47 +08:00
|
|
|
if (mgp_type_string(&string) != MGP_ERROR_NO_ERROR) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (mgp_proc_add_result(proc, "result", string) != MGP_ERROR_NO_ERROR) {
|
|
|
|
return 1;
|
|
|
|
}
|
2021-09-09 22:10:19 +08:00
|
|
|
struct mgp_type *list_of_anything = NULL;
|
2021-09-09 16:44:47 +08:00
|
|
|
if (mgp_type_list(nullable_any_type, &list_of_anything) != MGP_ERROR_NO_ERROR) {
|
2019-11-14 22:54:10 +08:00
|
|
|
return 1;
|
2021-09-09 16:44:47 +08:00
|
|
|
}
|
|
|
|
if (mgp_proc_add_result(proc, "args", list_of_anything)) {
|
|
|
|
return 1;
|
|
|
|
}
|
Integrate loading openCypher module procedures
Summary:
All mgp_* symbols are exported from Memgraph executable, no other
symbols should be visible.
The primary C API header, mg_procedure.h, is now part of the
installation. Also, added a shippable query module example.
Directory `query_modules` is meant to contain sources of modules we
write and ship as part of the installation. Currently, there's only an
example module, but there may be potentially more. Some modules could
only be installed as part of the enterprise release.
For Memgraph to load custom procedures, it needs to be started with a
flag pointing to a directory with compiled shared libraries implementing
those procedures.
Reviewers: mferencevic, ipaljak, llugovic, dsantl, buda
Reviewed By: mferencevic
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D2538
2019-10-31 23:36:34 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-10-02 01:33:46 +08:00
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
Integrate loading openCypher module procedures
Summary:
All mgp_* symbols are exported from Memgraph executable, no other
symbols should be visible.
The primary C API header, mg_procedure.h, is now part of the
installation. Also, added a shippable query module example.
Directory `query_modules` is meant to contain sources of modules we
write and ship as part of the installation. Currently, there's only an
example module, but there may be potentially more. Some modules could
only be installed as part of the enterprise release.
For Memgraph to load custom procedures, it needs to be started with a
flag pointing to a directory with compiled shared libraries implementing
those procedures.
Reviewers: mferencevic, ipaljak, llugovic, dsantl, buda
Reviewed By: mferencevic
Subscribers: pullbot
Differential Revision: https://phabricator.memgraph.io/D2538
2019-10-31 23:36:34 +08:00
|
|
|
// 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.
|
|
|
|
int mgp_shutdown_module() {
|
|
|
|
// Return 0 to indicate success.
|
|
|
|
return 0;
|
|
|
|
}
|