Skip to content
This repository was archived by the owner on Jan 23, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cpp/memgraph
Submodule memgraph updated 440 files
92 changes: 92 additions & 0 deletions cpp/text_module/algorithm/text.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "text.hpp"

#include <algorithm>
#include <regex>
#include <vector>

Expand Down Expand Up @@ -101,3 +102,94 @@ void Text::RegexGroups(mgp_list *args, mgp_graph * /*memgraph_graph*/, mgp_resul
record_factory.SetErrorMessage(e.what());
}
}

void Text::Replace(mgp_list *args, mgp_func_context * /*ctx*/, mgp_func_result *result, mgp_memory *memory) {
mgp::MemoryDispatcherGuard guard{memory};
const auto arguments = mgp::List(args);
mgp::Result result_obj(result);

try {
const auto text = std::string(arguments[0].ValueString());
Comment thread
Josipmrden marked this conversation as resolved.
Outdated
const auto regex = std::string(arguments[1].ValueString());
Comment thread
as51340 marked this conversation as resolved.
const auto replacement = std::string(arguments[2].ValueString());

if (regex.size() == 0) {
result_obj.SetValue(text);
return;
}

std::string result_str = text;
Comment thread
Josipmrden marked this conversation as resolved.
Outdated
size_t pos = 0;
while ((pos = result_str.find(regex, pos)) != std::string::npos) {
result_str.replace(pos, regex.length(), replacement);
pos += replacement.length();
}

result_obj.SetValue(result_str);
Comment thread
Josipmrden marked this conversation as resolved.
Outdated
} catch (const std::exception &e) {
result_obj.SetErrorMessage(e.what());
return;
}
}

void Text::RegReplace(mgp_list *args, mgp_func_context * /*ctx*/, mgp_func_result *result, mgp_memory *memory) {
mgp::MemoryDispatcherGuard guard{memory};
const auto arguments = mgp::List(args);
mgp::Result result_obj(result);

try {
const auto text = std::string(arguments[0].ValueString());
const auto regex = std::string(arguments[1].ValueString());
const auto replacement = std::string(arguments[2].ValueString());

if (regex.size() == 0) {
result_obj.SetValue(text);
return;
}

std::regex pattern(regex);
std::string result_str = std::regex_replace(text, pattern, replacement);

result_obj.SetValue(result_str);
Comment thread
Josipmrden marked this conversation as resolved.
Outdated
} catch (const std::exception &e) {
result_obj.SetErrorMessage(e.what());
return;
}
}

void Text::Distance(mgp_list *args, mgp_func_context * /*ctx*/, mgp_func_result *result, mgp_memory *memory) {
Comment thread
as51340 marked this conversation as resolved.
mgp::MemoryDispatcherGuard guard{memory};
const auto arguments = mgp::List(args);
mgp::Result result_obj(result);

try {
const auto text1 = std::string(arguments[0].ValueString());
const auto text2 = std::string(arguments[1].ValueString());

const size_t m = text1.length();
const size_t n = text2.length();
std::vector<std::vector<int>> dp(m + 1, std::vector<int>(n + 1));

for (size_t i = 0; i <= m; i++) {
dp[i][0] = i;
}
for (size_t j = 0; j <= n; j++) {
dp[0][j] = j;
}

for (size_t i = 1; i <= m; i++) {
for (size_t j = 1; j <= n; j++) {
if (text1[i - 1] == text2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1];
} else {
dp[i][j] = 1 + std::min({dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]});
}
}
}

result_obj.SetValue(static_cast<int64_t>(dp[m][n]));
} catch (const std::exception &e) {
result_obj.SetErrorMessage(e.what());
return;
}
}
16 changes: 16 additions & 0 deletions cpp/text_module/algorithm/text.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#pragma once

#include <string>
#include <string_view>

#include <mgp.hpp>

namespace Text {
Expand All @@ -19,8 +22,21 @@ constexpr std::string_view kProcedureRegexGroups = "regexGroups";
constexpr std::string_view kInput = "input";
constexpr std::string_view kRegex = "regex";
constexpr std::string_view kResultRegexGroups = "results";
/* replace constants */
constexpr std::string_view kProcedureReplace = "replace";
constexpr std::string_view kText = "text";
constexpr std::string_view kReplacement = "replacement";
/* regreplace constants */
constexpr std::string_view kProcedureRegReplace = "regreplace";
/* distance constants */
constexpr std::string_view kProcedureDistance = "distance";
constexpr std::string_view kText1 = "text1";
constexpr std::string_view kText2 = "text2";

void Join(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory);
void Format(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory);
void RegexGroups(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory);
void Replace(mgp_list *args, mgp_func_context *ctx, mgp_func_result *result, mgp_memory *memory);
void RegReplace(mgp_list *args, mgp_func_context *ctx, mgp_func_result *result, mgp_memory *memory);
void Distance(mgp_list *args, mgp_func_context *ctx, mgp_func_result *result, mgp_memory *memory);
} // namespace Text
17 changes: 17 additions & 0 deletions cpp/text_module/text_module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,23 @@ extern "C" int mgp_init_module(struct mgp_module *module, struct mgp_memory *mem
{mgp::Parameter(Text::kInput, mgp::Type::String),
mgp::Parameter(Text::kRegex, mgp::Type::String)},
{mgp::Return(Text::kResultRegexGroups, {mgp::Type::List, mgp::Type::Any})}, module, memory);

mgp::AddFunction(Text::Replace, Text::kProcedureReplace,
{mgp::Parameter(Text::kText, mgp::Type::String),
mgp::Parameter(Text::kRegex, mgp::Type::String),
mgp::Parameter(Text::kReplacement, mgp::Type::String)},
module, memory);

mgp::AddFunction(Text::RegReplace, Text::kProcedureRegReplace,
{mgp::Parameter(Text::kText, mgp::Type::String),
mgp::Parameter(Text::kRegex, mgp::Type::String),
mgp::Parameter(Text::kReplacement, mgp::Type::String)},
module, memory);

mgp::AddFunction(Text::Distance, Text::kProcedureDistance,
{mgp::Parameter(Text::kText1, mgp::Type::String),
mgp::Parameter(Text::kText2, mgp::Type::String)},
module, memory);
} catch (const std::exception &e) {
return 1;
}
Expand Down
Empty file.
4 changes: 4 additions & 0 deletions e2e/text_test/test_distance_basic/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
query: |
RETURN text.distance("Levenshtein", "Levenstein") AS output;
output:
- output: 1
Empty file.
4 changes: 4 additions & 0 deletions e2e/text_test/test_distance_different/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
query: |
RETURN text.distance("Hello", "World") AS output;
output:
- output: 4
Empty file.
4 changes: 4 additions & 0 deletions e2e/text_test/test_distance_empty/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
query: |
RETURN text.distance("", "") AS output;
output:
- output: 0
Empty file.
4 changes: 4 additions & 0 deletions e2e/text_test/test_distance_levenshtein/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
query: |
RETURN text.distance("Levenshtein", "Levenstein") AS output;
output:
- output: 1
Empty file.
5 changes: 5 additions & 0 deletions e2e/text_test/test_regreplace_basic/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
query: >
RETURN text.regreplace("Hello World!", "W[a-z]+", "Memgraph") AS output;

output:
- output: "Hello Memgraph!"
Empty file.
5 changes: 5 additions & 0 deletions e2e/text_test/test_regreplace_empty/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
query: >
RETURN text.regreplace("Hello World!", "", "Memgraph") AS output;

output:
- output: "Hello World!"
Empty file.
5 changes: 5 additions & 0 deletions e2e/text_test/test_regreplace_mage/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
query: >
RETURN text.regreplace("Memgraph MAGE Memgraph MAGE!", "MAGE", "GQLAlchemy") AS output;

output:
- output: "Memgraph GQLAlchemy Memgraph GQLAlchemy!"
Empty file.
5 changes: 5 additions & 0 deletions e2e/text_test/test_regreplace_multiple/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
query: >
RETURN text.regreplace("Hello World! Hello World!", "W[a-z]+", "Memgraph") AS output;

output:
- output: "Hello Memgraph! Hello Memgraph!"
Empty file.
5 changes: 5 additions & 0 deletions e2e/text_test/test_replace_basic/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
query: >
RETURN text.replace("Hello World!", "World", "Memgraph") AS output;

output:
- output: "Hello Memgraph!"
Empty file.
5 changes: 5 additions & 0 deletions e2e/text_test/test_replace_empty/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
query: >
RETURN text.replace("Hello World!", "", "Memgraph") AS output;

output:
- output: "Hello World!"
Empty file.
5 changes: 5 additions & 0 deletions e2e/text_test/test_replace_mage/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
query: >
RETURN text.replace("MAGE is a Memgraph product", "MAGE", "GQLAlchemy") AS output;

output:
- output: "GQLAlchemy is a Memgraph product"
Empty file.
5 changes: 5 additions & 0 deletions e2e/text_test/test_replace_multiple/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
query: >
RETURN text.replace("Hello World! Hello World!", "World", "Memgraph") AS output;

output:
- output: "Hello Memgraph! Hello Memgraph!"