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 all 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
91 changes: 91 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,93 @@ 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 {
auto text = std::string(arguments[0].ValueString());
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;
}

size_t pos = 0;
while ((pos = text.find(regex, pos)) != std::string::npos) {
text.replace(pos, regex.length(), replacement);
pos += replacement.length();
}

result_obj.SetValue(std::move(text));
} 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(std::move(result_str));
} 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!"