Skip to content

Commit b46871e

Browse files
Convert to_tree from function to procedure (memgraph#3148)
- Change convert_to_tree function to convert_to_tree_proc procedure - Update procedure signature to use mgp_result instead of mgp_func_result - Use correct procedure API: mgp::result_new_record() and mgp::result_record_insert() - Add mgp::ProcedureType::Read parameter to AddProcedure() - Update all test files to use CALL convert.to_tree() YIELD tree syntax - Remove old function registration and keep only procedure registration This converts the to_tree functionality from a function that returns a single value to a procedure that returns records, which is more appropriate for structured data.
1 parent ac8784f commit b46871e

5 files changed

Lines changed: 39 additions & 8 deletions

File tree

query_modules/convert.cpp

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ void str2object(mgp_list *args, mgp_func_context *ctx, mgp_func_result *res, mgp
382382
if (!maybe_result.has_value()) {
383383
mgp::func_result_set_error_msg(
384384
res,
385-
"The end result is not one of the following JSON-language data types: object, array, "
385+
"The end result is not one of the following JSON-language data types: object, array, "
386386
"number, string, boolean, or null.",
387387
memory);
388388
return;
@@ -440,15 +440,46 @@ void convert_to_tree(mgp_list *args, mgp_func_context *ctx, mgp_func_result *fun
440440
}
441441
}
442442

443+
void convert_to_tree_proc(mgp_list *args, mgp_graph *graph, mgp_result *result, mgp_memory *memory) {
444+
try {
445+
mgp::MemoryDispatcherGuard guard(memory);
446+
const auto arguments = mgp::List(args);
447+
const auto record = arguments[0];
448+
449+
// Create a default empty config if none provided
450+
mgp::Map config;
451+
if (arguments.Size() > 1) {
452+
config = arguments[1].ValueMap();
453+
}
454+
455+
// Convert the input value to tree structure
456+
auto result_value = ConvertToTreeImpl(record, config, memory);
457+
458+
// Create a new record for the result
459+
auto *result_record = mgp::result_new_record(result);
460+
461+
// We know the result will be a Map, so handle it directly
462+
if (result_value.IsMap()) {
463+
mgp::result_record_insert(result_record, "tree", result_value.ptr());
464+
} else {
465+
// For any other type (shouldn't happen in our case), return null
466+
mgp::result_record_insert(result_record, "tree", mgp::Value().ptr());
467+
}
468+
469+
} catch (const std::exception &e) {
470+
mgp::result_set_error_msg(result, e.what());
471+
}
472+
}
473+
443474
extern "C" int mgp_init_module(struct mgp_module *module, struct mgp_memory *memory) {
444475
try {
445476
mgp::MemoryDispatcherGuard guard(memory);
446477

447478
mgp::AddFunction(str2object, "str2object", {mgp::Parameter("string", mgp::Type::String)}, module, memory);
448-
mgp::AddFunction(
449-
convert_to_tree, "to_tree",
479+
mgp::AddProcedure(
480+
convert_to_tree_proc, "to_tree", mgp::ProcedureType::Read,
450481
{mgp::Parameter("value", mgp::Type::Any), mgp::Parameter("config", mgp::Type::Map, mgp::Value(mgp::Map()))},
451-
module, memory);
482+
{mgp::Return("tree", mgp::Type::Any)}, module, memory);
452483

453484
} catch (const std::exception &e) {
454485
std::cerr << "Error while initializing query module: " << e.what() << '\n';

tests/query_modules/to_tree_test/test_complex/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
query: >
22
MATCH p = (a:Student {name: 'Ana'})-[*]->(e:Student {name: 'Eve'})
33
WITH collect(p) AS paths
4-
WITH convert.to_tree(paths) AS tree
4+
CALL convert.to_tree(paths) YIELD tree
55
RETURN tree.name AS name, tree._type AS type, size(tree.FRIEND) AS friend_count, size(tree.COLLEAGUE) AS colleague_count
66
77
output:

tests/query_modules/to_tree_test/test_default_config/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
query: >
22
MATCH p = (a:Student {name: 'Ana'})-[:FRIEND]->(b:Student {name: 'Bob'})
33
WITH collect(p) AS paths
4-
WITH convert.to_tree(paths) AS tree
4+
CALL convert.to_tree(paths) YIELD tree
55
RETURN tree._type AS type, tree.name AS name, tree.age AS age, size(tree.FRIEND) AS friend_count
66
output:
77
- type: Student

tests/query_modules/to_tree_test/test_invalid_filter/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
query: >
22
MATCH p = (a:Student {name: 'Ana'})-[:FRIEND]->(b:Student {name: 'Bob'})
33
WITH collect(p) AS paths
4-
WITH convert.to_tree(paths, {nodes: {Student: [123, "name"]}}) AS tree
4+
CALL convert.to_tree(paths, {nodes: {Student: [123, "name"]}}) YIELD tree
55
RETURN tree._type AS type, tree.name AS name, tree.age AS age, size(tree.FRIEND) AS friend_count
66
output:
77
- type: Student

tests/query_modules/to_tree_test/test_simple/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
query: >
22
MATCH p = (a:Student {name: 'Ana'})-[:FRIEND*]->(c)
33
WITH collect(p) AS paths
4-
WITH convert.to_tree(paths) AS tree
4+
CALL convert.to_tree(paths) YIELD tree
55
RETURN tree.name AS name, tree._type AS type, size(tree.FRIEND) AS friend_count
66
77
output:

0 commit comments

Comments
 (0)