memgraph/tests/unit/query_trigger.cpp
antonio2368 883f9c7ed3 Trigger event types (#144)
Co-authored-by: Benjamin Antal <benjamin.antal@memgraph.io>
2021-05-26 14:13:14 +02:00

554 lines
28 KiB
C++

#include <gtest/gtest.h>
#include <filesystem>
#include "query/db_accessor.hpp"
#include "query/interpreter.hpp"
#include "query/trigger.hpp"
#include "query/typed_value.hpp"
#include "utils/memory.hpp"
class TriggerContextTest : public ::testing::Test {
public:
void SetUp() override { db.emplace(); }
void TearDown() override {
accessors.clear();
db.reset();
}
storage::Storage::Accessor &StartTransaction() {
accessors.push_back(db->Access());
return accessors.back();
}
protected:
std::optional<storage::Storage> db;
std::list<storage::Storage::Accessor> accessors;
};
namespace {
void CheckTypedValueSize(const query::TriggerContext &trigger_context, const query::TriggerIdentifierTag tag,
const size_t expected_size, query::DbAccessor &dba) {
auto typed_values = trigger_context.GetTypedValue(tag, &dba);
ASSERT_TRUE(typed_values.IsList());
ASSERT_EQ(typed_values.ValueList().size(), expected_size);
};
void CheckLabelMap(const query::TriggerContext &trigger_context, const query::TriggerIdentifierTag tag,
const size_t expected, query::DbAccessor &dba) {
auto typed_values = trigger_context.GetTypedValue(tag, &dba);
ASSERT_TRUE(typed_values.IsMap());
auto &typed_values_map = typed_values.ValueMap();
size_t value_count = 0;
for (const auto &[label, values] : typed_values_map) {
ASSERT_TRUE(values.IsList());
value_count += values.ValueList().size();
}
ASSERT_EQ(value_count, expected);
};
} // namespace
// Ensure that TriggerContext returns only valid objects.
// Returned TypedValue should always contain only objects
// that exist (unless its explicitly created for the deleted object)
TEST_F(TriggerContextTest, ValidObjectsTest) {
query::TriggerContext trigger_context;
query::TriggerContextCollector trigger_context_collector;
size_t vertex_count = 0;
size_t edge_count = 0;
{
query::DbAccessor dba{&StartTransaction()};
auto create_vertex = [&] {
auto created_vertex = dba.InsertVertex();
trigger_context_collector.RegisterCreatedObject(created_vertex);
++vertex_count;
return created_vertex;
};
// Create vertices and add them to the trigger context as created
std::vector<query::VertexAccessor> vertices;
for (size_t i = 0; i < 4; ++i) {
vertices.push_back(create_vertex());
}
auto create_edge = [&](auto &from, auto &to) {
auto maybe_edge = dba.InsertEdge(&from, &to, dba.NameToEdgeType("EDGE"));
ASSERT_FALSE(maybe_edge.HasError());
trigger_context_collector.RegisterCreatedObject(*maybe_edge);
++edge_count;
};
// Create edges and add them to the trigger context as created
create_edge(vertices[0], vertices[1]);
create_edge(vertices[1], vertices[2]);
create_edge(vertices[2], vertices[3]);
dba.AdvanceCommand();
trigger_context = std::move(trigger_context_collector).TransformToTriggerContext();
trigger_context_collector = query::TriggerContextCollector{};
// Should have all the created objects
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::CREATED_VERTICES, vertex_count, dba);
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::CREATED_EDGES, edge_count, dba);
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::CREATED_OBJECTS, vertex_count + edge_count, dba);
// we delete one of the vertices and edges in the same transaction
ASSERT_TRUE(dba.DetachRemoveVertex(&vertices[0]).HasValue());
--vertex_count;
--edge_count;
dba.AdvanceCommand();
// Should have one less created object for vertex and edge
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::CREATED_VERTICES, vertex_count, dba);
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::CREATED_EDGES, edge_count, dba);
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::CREATED_OBJECTS, vertex_count + edge_count, dba);
ASSERT_FALSE(dba.Commit().HasError());
}
{
query::DbAccessor dba{&StartTransaction()};
trigger_context.AdaptForAccessor(&dba);
// Should have one less created object for vertex and edge
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::CREATED_VERTICES, vertex_count, dba);
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::CREATED_EDGES, edge_count, dba);
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::CREATED_OBJECTS, vertex_count + edge_count, dba);
}
size_t deleted_vertex_count = 0;
size_t deleted_edge_count = 0;
{
query::DbAccessor dba{&StartTransaction()};
// register each type of change for each object
{
auto vertices = dba.Vertices(storage::View::OLD);
for (auto vertex : vertices) {
trigger_context_collector.RegisterSetObjectProperty(vertex, dba.NameToProperty("PROPERTY1"),
query::TypedValue("Value"), query::TypedValue("ValueNew"));
trigger_context_collector.RegisterRemovedObjectProperty(vertex, dba.NameToProperty("PROPERTY2"),
query::TypedValue("Value"));
trigger_context_collector.RegisterSetVertexLabel(vertex, dba.NameToLabel("LABEL1"));
trigger_context_collector.RegisterRemovedVertexLabel(vertex, dba.NameToLabel("LABEL2"));
auto out_edges = vertex.OutEdges(storage::View::OLD);
ASSERT_TRUE(out_edges.HasValue());
for (auto edge : *out_edges) {
trigger_context_collector.RegisterSetObjectProperty(
edge, dba.NameToProperty("PROPERTY1"), query::TypedValue("Value"), query::TypedValue("ValueNew"));
trigger_context_collector.RegisterRemovedObjectProperty(edge, dba.NameToProperty("PROPERTY2"),
query::TypedValue("Value"));
}
}
}
// Delete the first vertex with its edge and register the deleted object
{
auto vertices = dba.Vertices(storage::View::OLD);
for (auto vertex : vertices) {
const auto maybe_values = dba.DetachRemoveVertex(&vertex);
ASSERT_TRUE(maybe_values.HasValue());
ASSERT_TRUE(maybe_values.GetValue());
const auto &[deleted_vertex, deleted_edges] = *maybe_values.GetValue();
trigger_context_collector.RegisterDeletedObject(deleted_vertex);
++deleted_vertex_count;
--vertex_count;
for (const auto &edge : deleted_edges) {
trigger_context_collector.RegisterDeletedObject(edge);
++deleted_edge_count;
--edge_count;
}
break;
}
}
dba.AdvanceCommand();
ASSERT_FALSE(dba.Commit().HasError());
trigger_context = std::move(trigger_context_collector).TransformToTriggerContext();
trigger_context_collector = query::TriggerContextCollector{};
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::SET_VERTEX_PROPERTIES, vertex_count, dba);
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::SET_EDGE_PROPERTIES, edge_count, dba);
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::REMOVED_VERTEX_PROPERTIES, vertex_count, dba);
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::REMOVED_EDGE_PROPERTIES, edge_count, dba);
CheckLabelMap(trigger_context, query::TriggerIdentifierTag::SET_VERTEX_LABELS, vertex_count, dba);
CheckLabelMap(trigger_context, query::TriggerIdentifierTag::REMOVED_VERTEX_LABELS, vertex_count, dba);
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::UPDATED_VERTICES, 4 * vertex_count, dba);
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::UPDATED_EDGES, 2 * edge_count, dba);
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::UPDATED_OBJECTS,
4 * vertex_count + 2 * edge_count, dba);
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::DELETED_VERTICES, deleted_vertex_count, dba);
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::DELETED_EDGES, deleted_edge_count, dba);
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::DELETED_OBJECTS,
deleted_vertex_count + deleted_edge_count, dba);
}
// delete a single vertex with its edges, it should reduce number of typed values returned by the trigger context
// for each update event.
// TypedValue of the deleted objects stay the same as they're bound to the transaction which deleted them.
{
query::DbAccessor dba{&StartTransaction()};
trigger_context.AdaptForAccessor(&dba);
auto vertices = dba.Vertices(storage::View::OLD);
for (auto vertex : vertices) {
ASSERT_TRUE(dba.DetachRemoveVertex(&vertex).HasValue());
break;
}
--vertex_count;
--edge_count;
ASSERT_FALSE(dba.Commit().HasError());
}
{
query::DbAccessor dba{&StartTransaction()};
trigger_context.AdaptForAccessor(&dba);
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::SET_VERTEX_PROPERTIES, vertex_count, dba);
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::SET_EDGE_PROPERTIES, edge_count, dba);
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::REMOVED_VERTEX_PROPERTIES, vertex_count, dba);
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::REMOVED_EDGE_PROPERTIES, edge_count, dba);
CheckLabelMap(trigger_context, query::TriggerIdentifierTag::SET_VERTEX_LABELS, vertex_count, dba);
CheckLabelMap(trigger_context, query::TriggerIdentifierTag::REMOVED_VERTEX_LABELS, vertex_count, dba);
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::UPDATED_VERTICES, 4 * vertex_count, dba);
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::UPDATED_EDGES, 2 * edge_count, dba);
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::UPDATED_OBJECTS,
4 * vertex_count + 2 * edge_count, dba);
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::DELETED_VERTICES, deleted_vertex_count, dba);
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::DELETED_EDGES, deleted_edge_count, dba);
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::DELETED_OBJECTS,
deleted_vertex_count + deleted_edge_count, dba);
}
}
// If the trigger context registered a created object, each future event on the same object will be ignored.
// Binding the trigger context to transaction will mean that creating and updating an object in the same transaction
// will return only the CREATE event.
TEST_F(TriggerContextTest, ReturnCreateOnlyEvent) {
query::TriggerContextCollector trigger_context_collector;
query::DbAccessor dba{&StartTransaction()};
auto create_vertex = [&] {
auto vertex = dba.InsertVertex();
trigger_context_collector.RegisterCreatedObject(vertex);
trigger_context_collector.RegisterSetObjectProperty(vertex, dba.NameToProperty("PROPERTY1"),
query::TypedValue("Value"), query::TypedValue("ValueNew"));
trigger_context_collector.RegisterRemovedObjectProperty(vertex, dba.NameToProperty("PROPERTY2"),
query::TypedValue("Value"));
trigger_context_collector.RegisterSetVertexLabel(vertex, dba.NameToLabel("LABEL1"));
trigger_context_collector.RegisterRemovedVertexLabel(vertex, dba.NameToLabel("LABEL2"));
return vertex;
};
auto v1 = create_vertex();
auto v2 = create_vertex();
auto maybe_edge = dba.InsertEdge(&v1, &v2, dba.NameToEdgeType("EDGE"));
ASSERT_FALSE(maybe_edge.HasError());
trigger_context_collector.RegisterCreatedObject(*maybe_edge);
trigger_context_collector.RegisterSetObjectProperty(*maybe_edge, dba.NameToProperty("PROPERTY1"),
query::TypedValue("Value"), query::TypedValue("ValueNew"));
trigger_context_collector.RegisterRemovedObjectProperty(*maybe_edge, dba.NameToProperty("PROPERTY2"),
query::TypedValue("Value"));
dba.AdvanceCommand();
const auto trigger_context = std::move(trigger_context_collector).TransformToTriggerContext();
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::CREATED_VERTICES, 2, dba);
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::CREATED_EDGES, 1, dba);
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::CREATED_OBJECTS, 3, dba);
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::SET_VERTEX_PROPERTIES, 0, dba);
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::SET_EDGE_PROPERTIES, 0, dba);
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::REMOVED_VERTEX_PROPERTIES, 0, dba);
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::REMOVED_EDGE_PROPERTIES, 0, dba);
CheckLabelMap(trigger_context, query::TriggerIdentifierTag::SET_VERTEX_LABELS, 0, dba);
CheckLabelMap(trigger_context, query::TriggerIdentifierTag::REMOVED_VERTEX_LABELS, 0, dba);
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::UPDATED_VERTICES, 0, dba);
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::UPDATED_EDGES, 0, dba);
CheckTypedValueSize(trigger_context, query::TriggerIdentifierTag::UPDATED_OBJECTS, 0, dba);
}
namespace {
void EXPECT_PROP_TRUE(const query::TypedValue &a) {
EXPECT_TRUE(a.type() == query::TypedValue::Type::Bool && a.ValueBool());
}
void EXPECT_PROP_EQ(const query::TypedValue &a, const query::TypedValue &b) { EXPECT_PROP_TRUE(a == b); }
} // namespace
// During a transaction, same property for the same object can change multiple times. TriggerContext should ensure
// that only the change on the global value is returned (value before the transaction + latest value after the
// transaction) everything inbetween should be ignored.
TEST_F(TriggerContextTest, GlobalPropertyChange) {
query::DbAccessor dba{&StartTransaction()};
auto v = dba.InsertVertex();
dba.AdvanceCommand();
{
SPDLOG_DEBUG("SET -> SET");
query::TriggerContextCollector trigger_context_collector;
trigger_context_collector.RegisterSetObjectProperty(v, dba.NameToProperty("PROPERTY"), query::TypedValue("Value"),
query::TypedValue("ValueNew"));
trigger_context_collector.RegisterSetObjectProperty(v, dba.NameToProperty("PROPERTY"),
query::TypedValue("ValueNew"), query::TypedValue("ValueNewer"));
const auto trigger_context = std::move(trigger_context_collector).TransformToTriggerContext();
auto updated_vertices = trigger_context.GetTypedValue(query::TriggerIdentifierTag::UPDATED_VERTICES, &dba);
ASSERT_TRUE(updated_vertices.IsList());
auto &updated_vertices_list = updated_vertices.ValueList();
ASSERT_EQ(updated_vertices_list.size(), 1);
auto &update = updated_vertices_list[0];
ASSERT_TRUE(update.IsMap());
EXPECT_PROP_EQ(update, query::TypedValue{std::map<std::string, query::TypedValue>{
{"event_type", query::TypedValue{"set_vertex_property"}},
{"vertex", query::TypedValue{v}},
{"key", query::TypedValue{"PROPERTY"}},
{"old", query::TypedValue{"Value"}},
{"new", query::TypedValue{"ValueNewer"}}}});
}
{
SPDLOG_DEBUG("SET -> REMOVE");
query::TriggerContextCollector trigger_context_collector;
trigger_context_collector.RegisterSetObjectProperty(v, dba.NameToProperty("PROPERTY"), query::TypedValue("Value"),
query::TypedValue("ValueNew"));
trigger_context_collector.RegisterRemovedObjectProperty(v, dba.NameToProperty("PROPERTY"),
query::TypedValue("ValueNew"));
const auto trigger_context = std::move(trigger_context_collector).TransformToTriggerContext();
auto updated_vertices = trigger_context.GetTypedValue(query::TriggerIdentifierTag::UPDATED_VERTICES, &dba);
ASSERT_TRUE(updated_vertices.IsList());
auto &updated_vertices_list = updated_vertices.ValueList();
ASSERT_EQ(updated_vertices_list.size(), 1);
auto &update = updated_vertices_list[0];
ASSERT_TRUE(update.IsMap());
EXPECT_PROP_EQ(update, query::TypedValue{std::map<std::string, query::TypedValue>{
{"event_type", query::TypedValue{"removed_vertex_property"}},
{"vertex", query::TypedValue{v}},
{"key", query::TypedValue{"PROPERTY"}},
{"old", query::TypedValue{"Value"}}}});
}
{
SPDLOG_DEBUG("REMOVE -> SET");
query::TriggerContextCollector trigger_context_collector;
trigger_context_collector.RegisterRemovedObjectProperty(v, dba.NameToProperty("PROPERTY"),
query::TypedValue("Value"));
trigger_context_collector.RegisterSetObjectProperty(v, dba.NameToProperty("PROPERTY"), query::TypedValue(),
query::TypedValue("ValueNew"));
const auto trigger_context = std::move(trigger_context_collector).TransformToTriggerContext();
auto updated_vertices = trigger_context.GetTypedValue(query::TriggerIdentifierTag::UPDATED_VERTICES, &dba);
ASSERT_TRUE(updated_vertices.IsList());
auto &updated_vertices_list = updated_vertices.ValueList();
ASSERT_EQ(updated_vertices_list.size(), 1);
auto &update = updated_vertices_list[0];
ASSERT_TRUE(update.IsMap());
EXPECT_PROP_EQ(update, query::TypedValue{std::map<std::string, query::TypedValue>{
{"event_type", query::TypedValue{"set_vertex_property"}},
{"vertex", query::TypedValue{v}},
{"key", query::TypedValue{"PROPERTY"}},
{"old", query::TypedValue{"Value"}},
{"new", query::TypedValue{"ValueNew"}}}});
}
{
SPDLOG_DEBUG("REMOVE -> REMOVE");
query::TriggerContextCollector trigger_context_collector;
trigger_context_collector.RegisterRemovedObjectProperty(v, dba.NameToProperty("PROPERTY"),
query::TypedValue("Value"));
trigger_context_collector.RegisterRemovedObjectProperty(v, dba.NameToProperty("PROPERTY"), query::TypedValue());
const auto trigger_context = std::move(trigger_context_collector).TransformToTriggerContext();
auto updated_vertices = trigger_context.GetTypedValue(query::TriggerIdentifierTag::UPDATED_VERTICES, &dba);
ASSERT_TRUE(updated_vertices.IsList());
auto &updated_vertices_list = updated_vertices.ValueList();
ASSERT_EQ(updated_vertices_list.size(), 1);
auto &update = updated_vertices_list[0];
ASSERT_TRUE(update.IsMap());
EXPECT_PROP_EQ(update, query::TypedValue{std::map<std::string, query::TypedValue>{
{"event_type", query::TypedValue{"removed_vertex_property"}},
{"vertex", query::TypedValue{v}},
{"key", query::TypedValue{"PROPERTY"}},
{"old", query::TypedValue{"Value"}}}});
}
{
SPDLOG_DEBUG("SET -> SET (no change on transaction level)");
query::TriggerContextCollector trigger_context_collector;
trigger_context_collector.RegisterSetObjectProperty(v, dba.NameToProperty("PROPERTY"), query::TypedValue("Value"),
query::TypedValue("ValueNew"));
trigger_context_collector.RegisterSetObjectProperty(v, dba.NameToProperty("PROPERTY"),
query::TypedValue("ValueNew"), query::TypedValue("Value"));
const auto trigger_context = std::move(trigger_context_collector).TransformToTriggerContext();
auto updated_vertices = trigger_context.GetTypedValue(query::TriggerIdentifierTag::UPDATED_VERTICES, &dba);
ASSERT_TRUE(updated_vertices.IsList());
auto &updated_vertices_list = updated_vertices.ValueList();
ASSERT_EQ(updated_vertices_list.size(), 0);
}
{
SPDLOG_DEBUG("SET -> REMOVE (no change on transaction level)");
query::TriggerContextCollector trigger_context_collector;
trigger_context_collector.RegisterSetObjectProperty(v, dba.NameToProperty("PROPERTY"), query::TypedValue(),
query::TypedValue("ValueNew"));
trigger_context_collector.RegisterRemovedObjectProperty(v, dba.NameToProperty("PROPERTY"),
query::TypedValue("ValueNew"));
const auto trigger_context = std::move(trigger_context_collector).TransformToTriggerContext();
auto updated_vertices = trigger_context.GetTypedValue(query::TriggerIdentifierTag::UPDATED_VERTICES, &dba);
ASSERT_TRUE(updated_vertices.IsList());
auto &updated_vertices_list = updated_vertices.ValueList();
ASSERT_EQ(updated_vertices_list.size(), 0);
}
{
SPDLOG_DEBUG("REMOVE -> SET (no change on transaction level)");
query::TriggerContextCollector trigger_context_collector;
trigger_context_collector.RegisterRemovedObjectProperty(v, dba.NameToProperty("PROPERTY"),
query::TypedValue("Value"));
trigger_context_collector.RegisterSetObjectProperty(v, dba.NameToProperty("PROPERTY"), query::TypedValue(),
query::TypedValue("Value"));
const auto trigger_context = std::move(trigger_context_collector).TransformToTriggerContext();
auto updated_vertices = trigger_context.GetTypedValue(query::TriggerIdentifierTag::UPDATED_VERTICES, &dba);
ASSERT_TRUE(updated_vertices.IsList());
auto &updated_vertices_list = updated_vertices.ValueList();
ASSERT_EQ(updated_vertices_list.size(), 0);
}
{
SPDLOG_DEBUG("REMOVE -> REMOVE (no change on transaction level)");
query::TriggerContextCollector trigger_context_collector;
trigger_context_collector.RegisterRemovedObjectProperty(v, dba.NameToProperty("PROPERTY"), query::TypedValue());
trigger_context_collector.RegisterRemovedObjectProperty(v, dba.NameToProperty("PROPERTY"), query::TypedValue());
const auto trigger_context = std::move(trigger_context_collector).TransformToTriggerContext();
auto updated_vertices = trigger_context.GetTypedValue(query::TriggerIdentifierTag::UPDATED_VERTICES, &dba);
ASSERT_TRUE(updated_vertices.IsList());
auto &updated_vertices_list = updated_vertices.ValueList();
ASSERT_EQ(updated_vertices_list.size(), 0);
}
{
SPDLOG_DEBUG("SET -> REMOVE -> SET -> REMOVE -> SET");
query::TriggerContextCollector trigger_context_collector;
trigger_context_collector.RegisterSetObjectProperty(v, dba.NameToProperty("PROPERTY"), query::TypedValue("Value0"),
query::TypedValue("Value1"));
trigger_context_collector.RegisterRemovedObjectProperty(v, dba.NameToProperty("PROPERTY"),
query::TypedValue("Value1"));
trigger_context_collector.RegisterSetObjectProperty(v, dba.NameToProperty("PROPERTY"), query::TypedValue(),
query::TypedValue("Value2"));
trigger_context_collector.RegisterRemovedObjectProperty(v, dba.NameToProperty("PROPERTY"),
query::TypedValue("Value2"));
trigger_context_collector.RegisterSetObjectProperty(v, dba.NameToProperty("PROPERTY"), query::TypedValue(),
query::TypedValue("Value3"));
const auto trigger_context = std::move(trigger_context_collector).TransformToTriggerContext();
auto updated_vertices = trigger_context.GetTypedValue(query::TriggerIdentifierTag::UPDATED_VERTICES, &dba);
ASSERT_TRUE(updated_vertices.IsList());
auto &updated_vertices_list = updated_vertices.ValueList();
ASSERT_EQ(updated_vertices_list.size(), 1);
auto &update = updated_vertices_list[0];
ASSERT_TRUE(update.IsMap());
EXPECT_PROP_EQ(update, query::TypedValue{std::map<std::string, query::TypedValue>{
{"event_type", query::TypedValue{"set_vertex_property"}},
{"vertex", query::TypedValue{v}},
{"key", query::TypedValue{"PROPERTY"}},
{"old", query::TypedValue{"Value0"}},
{"new", query::TypedValue{"Value3"}}}});
}
}
// Same as above, but for label changes
TEST_F(TriggerContextTest, GlobalLabelChange) {
query::DbAccessor dba{&StartTransaction()};
auto v = dba.InsertVertex();
dba.AdvanceCommand();
const auto label_id = dba.NameToLabel("LABEL");
// You cannot add the same label multiple times and you cannot remove non existing labels
// so REMOVE -> REMOVE and SET -> SET doesn't make sense
{
SPDLOG_DEBUG("SET -> REMOVE");
query::TriggerContextCollector trigger_context_collector;
trigger_context_collector.RegisterSetVertexLabel(v, label_id);
trigger_context_collector.RegisterRemovedVertexLabel(v, label_id);
const auto trigger_context = std::move(trigger_context_collector).TransformToTriggerContext();
auto updated_vertices = trigger_context.GetTypedValue(query::TriggerIdentifierTag::UPDATED_VERTICES, &dba);
ASSERT_TRUE(updated_vertices.IsList());
auto &updated_vertices_list = updated_vertices.ValueList();
ASSERT_EQ(updated_vertices_list.size(), 0);
}
{
SPDLOG_DEBUG("REMOVE -> SET");
query::TriggerContextCollector trigger_context_collector;
trigger_context_collector.RegisterRemovedVertexLabel(v, label_id);
trigger_context_collector.RegisterSetVertexLabel(v, label_id);
const auto trigger_context = std::move(trigger_context_collector).TransformToTriggerContext();
auto updated_vertices = trigger_context.GetTypedValue(query::TriggerIdentifierTag::UPDATED_VERTICES, &dba);
ASSERT_TRUE(updated_vertices.IsList());
auto &updated_vertices_list = updated_vertices.ValueList();
ASSERT_EQ(updated_vertices_list.size(), 0);
}
{
SPDLOG_DEBUG("SET -> REMOVE -> SET -> REMOVE -> SET");
query::TriggerContextCollector trigger_context_collector;
trigger_context_collector.RegisterSetVertexLabel(v, label_id);
trigger_context_collector.RegisterRemovedVertexLabel(v, label_id);
trigger_context_collector.RegisterSetVertexLabel(v, label_id);
trigger_context_collector.RegisterRemovedVertexLabel(v, label_id);
trigger_context_collector.RegisterSetVertexLabel(v, label_id);
const auto trigger_context = std::move(trigger_context_collector).TransformToTriggerContext();
auto updated_vertices = trigger_context.GetTypedValue(query::TriggerIdentifierTag::UPDATED_VERTICES, &dba);
ASSERT_TRUE(updated_vertices.IsList());
auto &updated_vertices_list = updated_vertices.ValueList();
ASSERT_EQ(updated_vertices_list.size(), 1);
auto &update = updated_vertices_list[0];
ASSERT_TRUE(update.IsMap());
EXPECT_PROP_EQ(update, query::TypedValue{std::map<std::string, query::TypedValue>{
{"event_type", query::TypedValue{"set_vertex_label"}},
{"vertex", query::TypedValue{v}},
{"label", query::TypedValue{"LABEL"}}}});
}
{
SPDLOG_DEBUG("REMOVE -> SET -> REMOVE -> SET -> REMOVE");
query::TriggerContextCollector trigger_context_collector;
trigger_context_collector.RegisterRemovedVertexLabel(v, label_id);
trigger_context_collector.RegisterSetVertexLabel(v, label_id);
trigger_context_collector.RegisterRemovedVertexLabel(v, label_id);
trigger_context_collector.RegisterSetVertexLabel(v, label_id);
trigger_context_collector.RegisterRemovedVertexLabel(v, label_id);
const auto trigger_context = std::move(trigger_context_collector).TransformToTriggerContext();
auto updated_vertices = trigger_context.GetTypedValue(query::TriggerIdentifierTag::UPDATED_VERTICES, &dba);
ASSERT_TRUE(updated_vertices.IsList());
auto &updated_vertices_list = updated_vertices.ValueList();
ASSERT_EQ(updated_vertices_list.size(), 1);
auto &update = updated_vertices_list[0];
ASSERT_TRUE(update.IsMap());
EXPECT_PROP_EQ(update, query::TypedValue{std::map<std::string, query::TypedValue>{
{"event_type", query::TypedValue{"removed_vertex_label"}},
{"vertex", query::TypedValue{v}},
{"label", query::TypedValue{"LABEL"}}}});
}
}