Skip to content
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
111 changes: 108 additions & 3 deletions cpp/collections_module/algorithm/collections.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,115 @@
#include "collections.hpp"
#include <algorithm>
#include <list>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <unordered_map>
#include "collections.hpp"

void Collections::SumLongs(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) {
mgp::memory = memory;
const auto arguments = mgp::List(args);
const auto record_factory = mgp::RecordFactory(result);

try {
int64_t sum{0};
const auto list{arguments[0].ValueList()};

for (const auto list_item : list) {
if (!list_item.IsNumeric()) {
std::ostringstream oss;
oss << list_item.Type();
throw mgp::ValueException("Unsupported type for this operation, received type: " + oss.str());
}
sum += static_cast<int64_t>(list_item.ValueNumeric());
}
auto record = record_factory.NewRecord();
record.Insert(std::string(kResultSumLongs).c_str(), sum);

} catch (const std::exception &e) {
record_factory.SetErrorMessage(e.what());
return;
}
}

void Collections::Avg(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) {
mgp::memory = memory;
const auto arguments = mgp::List(args);
const auto record_factory = mgp::RecordFactory(result);

try {
double average{0};
const auto list{arguments[0].ValueList()};

for (const auto list_item : list) {
if (!list_item.IsNumeric()) {
std::ostringstream oss;
oss << list_item.Type();
throw mgp::ValueException("Unsupported type for this operation, received type: " + oss.str());
}
average += list_item.ValueNumeric();
}
average /= list.Size();

auto record = record_factory.NewRecord();
record.Insert(std::string(kResultAvg).c_str(), average);

} catch (const std::exception &e) {
record_factory.SetErrorMessage(e.what());
return;
}
}

void Collections::ContainsAll(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) {
mgp::memory = memory;
const auto arguments = mgp::List(args);
const auto record_factory = mgp::RecordFactory(result);

try {
const auto list1{arguments[0].ValueList()};
std::unordered_set<mgp::Value> set{list1.begin(), list1.end()};
const auto list2{arguments[1].ValueList()};
std::unordered_set<mgp::Value> values{list2.begin(), list2.end()};

auto record = record_factory.NewRecord();
record.Insert(std::string(kResultContainsAll).c_str(),
std::all_of(values.begin(), values.end(), [&](const auto &x) { return set.contains(x); }));

} catch (const std::exception &e) {
record_factory.SetErrorMessage(e.what());
return;
}
}

void Collections::Intersection(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) {
mgp::memory = memory;
const auto arguments = mgp::List(args);
const auto record_factory = mgp::RecordFactory(result);

try {
const auto list1{arguments[0].ValueList()};
std::unordered_set<mgp::Value> set1{list1.begin(), list1.end()};
const auto list2{arguments[1].ValueList()};
std::unordered_set<mgp::Value> set2{list2.begin(), list2.end()};

if (set1.size() > set2.size()) {
std::swap(set1, set2);
}

mgp::List intersection{};
for (const auto &element : set1) {
if (set2.contains(element)) {
intersection.AppendExtend(std::move(element));
}
}

auto record = record_factory.NewRecord();
record.Insert(std::string(kResultIntersection).c_str(), intersection);

} catch (const std::exception &e) {
record_factory.SetErrorMessage(e.what());
return;
}
}

void Collections::RemoveAll(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) {
mgp::memory = memory;
Expand Down Expand Up @@ -298,7 +404,6 @@ void Collections::Contains(mgp_list *args, mgp_graph *memgraph_graph, mgp_result
}
}


void Collections::UnionAll(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) {
mgp::memory = memory;
auto arguments = mgp::List(args);
Expand Down
69 changes: 57 additions & 12 deletions cpp/collections_module/algorithm/collections.hpp
Original file line number Diff line number Diff line change
@@ -1,97 +1,142 @@
#pragma once

#include <mgp.hpp>
#include <string>
#include <sstream>
#include <string>
#include <string_view>

namespace Collections {

/* sum_longs constants */
constexpr const std::string_view kProcedureSumLongs = "sum_longs";
constexpr const std::string_view kSumLongsArg1 = "numbers";
constexpr const std::string_view kResultSumLongs = "sum";

/* avg constants */
constexpr const std::string_view kProcedureAvg = "avg";
constexpr const std::string_view kAvgArg1 = "numbers";
constexpr const std::string_view kResultAvg = "average";

/* contains_all constants */
constexpr const std::string_view kProcedureContainsAll = "contains_all";
constexpr const std::string_view kContainsAllArg1 = "collection";
constexpr const std::string_view kContainsAllArg2 = "values";
constexpr const std::string_view kResultContainsAll = "contained";

/* intersection constants */
constexpr const std::string_view kProcedureIntersection = "intersection";
constexpr const std::string_view kIntersectionArg1 = "first";
constexpr const std::string_view kIntersectionArg2 = "second";
constexpr const std::string_view kResultIntersection = "intersection";

/* remove_all constants */
constexpr std::string_view kProcedureRemoveAll = "remove_all";
constexpr std::string_view kReturnRemoveAll = "removed";
constexpr std::string_view kArgumentsInputList = "input_list";
constexpr std::string_view kArgumentsRemoveList = "to_remove_list";
constexpr std::string_view kResultRemoveAll = "removed";

/* sum constants */
constexpr std::string_view kReturnSum = "sum";
constexpr std::string_view kProcedureSum = "sum";
constexpr std::string_view kInputList = "input_list";
constexpr std::string_view kResultSum = "sum";

/* union constants */
constexpr std::string_view kReturnUnion = "union";
constexpr std::string_view kProcedureUnion = "union";
constexpr std::string_view kArgumentsInputList1 = "input_list1";
constexpr std::string_view kArgumentsInputList2 = "input_list2";
constexpr std::string_view kResultUnion = "union";

/* sorted constants */
constexpr std::string_view kReturnSort = "sorted";
constexpr std::string_view kProcedureSort = "sort";
constexpr std::string_view kResultSort = "sorted";

/* contains constants */
constexpr std::string_view kReturnCS = "contains";
constexpr std::string_view kProcedureCS = "contains_sorted";
constexpr std::string_view kArgumentInputList = "input_list";
constexpr std::string_view kArgumentElement = "element";
constexpr std::string_view kResultCS = "contains";

/* max constants */
constexpr std::string_view kReturnMax = "max";
constexpr std::string_view kProcedureMax = "max";
constexpr std::string_view kResultMax = "max";

/* split constants */
constexpr std::string_view kProcedureSplit = "split";
constexpr std::string_view kReturnSplit = "splitted";
constexpr std::string_view kArgumentDelimiter = "delimiter";
constexpr std::string_view kResultSplit = "splitted";

/* pairs constants */
constexpr std::string_view kReturnPairs = "pairs";
constexpr std::string_view kProcedurePairs = "pairs";
constexpr std::string_view kResultPairs = "pairs";

//Contains constants
/* contains constants */
constexpr std::string_view kReturnValueContains = "output";
constexpr std::string_view kProcedureContains = "contains";
constexpr std::string_view kArgumentListContains = "list";
constexpr std::string_view kArgumentValueContains = "value";


//UnionAll constants
/* union_all constants */
constexpr std::string_view kReturnValueUnionAll = "return_list";
constexpr std::string_view kProcedureUnionAll = "unionAll";
constexpr std::string_view kProcedureUnionAll = "union_all";
constexpr std::string_view kArgumentList1UnionAll = "list1";
constexpr std::string_view kArgumentList2UnionAll = "list2";


//Min constants
/* min constants */
constexpr std::string_view kReturnValueMin = "min";
constexpr std::string_view kProcedureMin = "min";
constexpr std::string_view kArgumentListMin = "list";


//ToSet constants
/* to_set constants */
constexpr std::string_view kReturnToSet = "result";
constexpr std::string_view kProcedureToSet = "to_set";
constexpr std::string_view kArgumentListToSet = "list";


//Partition constants
/* partition constants */
constexpr std::string_view kReturnValuePartition = "result";
constexpr std::string_view kProcedurePartition = "partition";
constexpr std::string_view kArgumentListPartition = "list";
constexpr std::string_view kArgumentSizePartition = "partition_size";

void SumLongs(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory);

void Avg(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory);

void ContainsAll(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory);

void Intersection(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory);

void RemoveAll(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory);

void Sum(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory);

void Union(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory);

void Sort(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory);

void ContainsSorted(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory);

void Max(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory);

void Split(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory);

void Pairs(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory);

void Contains(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory);

void UnionAll(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory);

void Min(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory);

void ToSet(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory);
void Partition(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory);

void Partition(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory);

} // namespace Collections
65 changes: 43 additions & 22 deletions cpp/collections_module/collections_module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,23 @@ extern "C" int mgp_init_module(struct mgp_module *module, struct mgp_memory *mem
try {
mgp::memory = memory;

AddProcedure(Collections::SumLongs, Collections::kProcedureSumLongs, mgp::ProcedureType::Read,
{mgp::Parameter(Collections::kSumLongsArg1, {mgp::Type::List, mgp::Type::Any})},
{mgp::Return(Collections::kResultSumLongs, mgp::Type::Int)}, module, memory);

AddProcedure(Collections::Avg, Collections::kProcedureAvg, mgp::ProcedureType::Read,
{mgp::Parameter(Collections::kAvgArg1, {mgp::Type::List, mgp::Type::Any})},
{mgp::Return(Collections::kResultAvg, mgp::Type::Double)}, module, memory);

AddProcedure(Collections::ContainsAll, Collections::kProcedureContainsAll, mgp::ProcedureType::Read,
{mgp::Parameter(Collections::kContainsAllArg1, {mgp::Type::List, mgp::Type::Any}),
mgp::Parameter(Collections::kContainsAllArg2, {mgp::Type::List, mgp::Type::Any})},
{mgp::Return(Collections::kResultContainsAll, mgp::Type::Bool)}, module, memory);

AddProcedure(Collections::Intersection, Collections::kProcedureIntersection, mgp::ProcedureType::Read,
{mgp::Parameter(Collections::kIntersectionArg1, {mgp::Type::List, mgp::Type::Any}),
mgp::Parameter(Collections::kIntersectionArg2, {mgp::Type::List, mgp::Type::Any})},
{mgp::Return(Collections::kResultIntersection, {mgp::Type::List, mgp::Type::Any})}, module, memory);
AddProcedure(Collections::RemoveAll, Collections::kProcedureRemoveAll, mgp::ProcedureType::Read,
{mgp::Parameter(Collections::kArgumentsInputList, {mgp::Type::List, mgp::Type::Any}),
mgp::Parameter(Collections::kArgumentsRemoveList, {mgp::Type::List, mgp::Type::Any})},
Expand Down Expand Up @@ -41,29 +58,33 @@ extern "C" int mgp_init_module(struct mgp_module *module, struct mgp_memory *mem
AddProcedure(Collections::Pairs, Collections::kProcedurePairs, mgp::ProcedureType::Read,
{mgp::Parameter(Collections::kInputList, {mgp::Type::List, mgp::Type::Any})},
{mgp::Return(Collections::kReturnPairs, {mgp::Type::List, mgp::Type::Any})}, module, memory);
AddProcedure(Collections::Contains, std::string(Collections::kProcedureContains).c_str(), mgp::ProcedureType::Read,
{mgp::Parameter(std::string(Collections::kArgumentListContains).c_str(), {mgp::Type::List, mgp::Type::Any}),
mgp::Parameter(std::string(Collections::kArgumentValueContains).c_str(), mgp::Type::Any)},
{mgp::Return(std::string(Collections::kReturnValueContains).c_str(), mgp::Type::Bool)}, module, memory);

AddProcedure(Collections::Min, std::string(Collections::kProcedureMin).c_str(), mgp::ProcedureType::Read,
{mgp::Parameter(std::string(Collections::kArgumentListMin).c_str(), {mgp::Type::List, mgp::Type::Any})},
{mgp::Return(std::string(Collections::kReturnValueMin).c_str(), mgp::Type::Any)}, module, memory);
AddProcedure(Collections::UnionAll, std::string(Collections::kProcedureUnionAll).c_str(), mgp::ProcedureType::Read,
{mgp::Parameter(std::string(Collections::kArgumentList1UnionAll).c_str(), {mgp::Type::List, mgp::Type::Any}),
mgp::Parameter(std::string(Collections::kArgumentList2UnionAll).c_str(), {mgp::Type::List, mgp::Type::Any})},
{mgp::Return(std::string(Collections::kReturnValueUnionAll).c_str(), {mgp::Type::List, mgp::Type::Any})},
module, memory);

AddProcedure(
Collections::Contains, std::string(Collections::kProcedureContains).c_str(), mgp::ProcedureType::Read,
{mgp::Parameter(std::string(Collections::kArgumentListContains).c_str(), {mgp::Type::List, mgp::Type::Any}),
mgp::Parameter(std::string(Collections::kArgumentValueContains).c_str(), mgp::Type::Any)},
{mgp::Return(std::string(Collections::kReturnValueContains).c_str(), mgp::Type::Bool)}, module, memory);

AddProcedure(
Collections::Min, std::string(Collections::kProcedureMin).c_str(), mgp::ProcedureType::Read,
{mgp::Parameter(std::string(Collections::kArgumentListMin).c_str(), {mgp::Type::List, mgp::Type::Any})},
{mgp::Return(std::string(Collections::kReturnValueMin).c_str(), mgp::Type::Any)}, module, memory);
AddProcedure(
Collections::UnionAll, std::string(Collections::kProcedureUnionAll).c_str(), mgp::ProcedureType::Read,
{mgp::Parameter(std::string(Collections::kArgumentList1UnionAll).c_str(), {mgp::Type::List, mgp::Type::Any}),
mgp::Parameter(std::string(Collections::kArgumentList2UnionAll).c_str(), {mgp::Type::List, mgp::Type::Any})},
{mgp::Return(std::string(Collections::kReturnValueUnionAll).c_str(), {mgp::Type::List, mgp::Type::Any})},
module, memory);

AddProcedure(Collections::ToSet, Collections::kProcedureToSet, mgp::ProcedureType::Read,
{mgp::Parameter(Collections::kArgumentListToSet, {mgp::Type::List, mgp::Type::Any})},
{mgp::Return(Collections::kReturnToSet, {mgp::Type::List, mgp::Type::Any})}, module, memory);

AddProcedure(Collections::Partition, std::string(Collections::kProcedurePartition).c_str(), mgp::ProcedureType::Read,
{mgp::Parameter(std::string(Collections::kArgumentListPartition).c_str(), {mgp::Type::List, mgp::Type::Any}),
mgp::Parameter(std::string(Collections::kArgumentSizePartition).c_str(), mgp::Type::Int)},
{mgp::Return(std::string(Collections::kReturnValuePartition).c_str(), {mgp::Type::List, mgp::Type::Any})},
module, memory);
{mgp::Parameter(Collections::kArgumentListToSet, {mgp::Type::List, mgp::Type::Any})},
{mgp::Return(Collections::kReturnToSet, {mgp::Type::List, mgp::Type::Any})}, module, memory);

AddProcedure(
Collections::Partition, std::string(Collections::kProcedurePartition).c_str(), mgp::ProcedureType::Read,
{mgp::Parameter(std::string(Collections::kArgumentListPartition).c_str(), {mgp::Type::List, mgp::Type::Any}),
mgp::Parameter(std::string(Collections::kArgumentSizePartition).c_str(), mgp::Type::Int)},
{mgp::Return(std::string(Collections::kReturnValuePartition).c_str(), {mgp::Type::List, mgp::Type::Any})},
module, memory);

} catch (const std::exception &e) {
return 1;
Expand Down
Empty file.
5 changes: 5 additions & 0 deletions e2e/collections_test/test_avg_different_types/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
query: >
CALL collections.avg([-5, 5, 2.2, -8.6, 0, 1.0])
YIELD average;
output:
- average: -0.8999999999999999
Empty file.
5 changes: 5 additions & 0 deletions e2e/collections_test/test_avg_negative/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
query: >
CALL collections.avg([5, 5, 6, 7, -5])
YIELD average;
output:
- average: 3.6
Empty file.
5 changes: 5 additions & 0 deletions e2e/collections_test/test_avg_positive/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
query: >
CALL collections.avg([1, 2, 3])
YIELD average;
output:
- average: 2.0
Empty file.
5 changes: 5 additions & 0 deletions e2e/collections_test/test_contains_all_1/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
query: >
CALL collections.contains_all([1, 2, 3, "pero"], [1, 1, 1, 1, 2, 3])
YIELD contained;
output:
- contained: true
Empty file.
5 changes: 5 additions & 0 deletions e2e/collections_test/test_contains_all_2/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
query: >
CALL collections.contains_all(["Pero", 1, 2, 3], ["Pero", 3])
YIELD contained;
output:
- contained: true
Empty file.
5 changes: 5 additions & 0 deletions e2e/collections_test/test_contains_all_3/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
query: >
CALL collections.contains_all([false, true], [0, 1])
YIELD contained return contained;
output:
- contained: false
Empty file.
Loading