Add functions for listing indices and constraints
Reviewers: teon.banek Reviewed By: teon.banek Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D2371
This commit is contained in:
parent
6d9933373e
commit
73379bc57e
src/storage/v2
tests/unit
@ -72,4 +72,10 @@ ValidateExistenceConstraints(Vertex *vertex, Constraints *constraints) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
/// Returns a list of all created existence constraints.
|
||||
inline std::vector<std::pair<LabelId, PropertyId>> ListExistenceConstraints(
|
||||
const Constraints &constraints) {
|
||||
return constraints.existence_constraints;
|
||||
}
|
||||
|
||||
} // namespace storage
|
||||
|
@ -298,6 +298,16 @@ void LabelIndex::UpdateOnAddLabel(LabelId label, Vertex *vertex,
|
||||
GetOrCreateStorage(label)->access().insert(Entry{vertex, tx.start_timestamp});
|
||||
}
|
||||
|
||||
std::vector<LabelId> LabelIndex::ListIndices() const {
|
||||
std::vector<LabelId> ret;
|
||||
ret.reserve(index_.size());
|
||||
auto acc = index_.access();
|
||||
for (const auto &item : acc) {
|
||||
ret.push_back(item.label);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void LabelIndex::RemoveObsoleteEntries(uint64_t oldest_active_start_timestamp) {
|
||||
auto index_acc = index_.access();
|
||||
for (auto &label_storage : index_acc) {
|
||||
@ -463,6 +473,16 @@ bool LabelPropertyIndex::CreateIndex(
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<std::pair<LabelId, PropertyId>> LabelPropertyIndex::ListIndices()
|
||||
const {
|
||||
std::vector<std::pair<LabelId, PropertyId>> ret;
|
||||
ret.reserve(index_.size());
|
||||
for (const auto &item : index_) {
|
||||
ret.push_back(item.first);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void LabelPropertyIndex::RemoveObsoleteEntries(
|
||||
uint64_t oldest_active_start_timestamp) {
|
||||
for (auto &[label_property, index] : index_) {
|
||||
|
@ -45,6 +45,8 @@ class LabelIndex {
|
||||
/// @throw std::bad_alloc
|
||||
void UpdateOnAddLabel(LabelId label, Vertex *vertex, const Transaction &tx);
|
||||
|
||||
std::vector<LabelId> ListIndices() const;
|
||||
|
||||
void RemoveObsoleteEntries(uint64_t oldest_active_start_timestamp);
|
||||
|
||||
class Iterable {
|
||||
@ -142,6 +144,8 @@ class LabelPropertyIndex {
|
||||
return index_.find({label, property}) != index_.end();
|
||||
}
|
||||
|
||||
std::vector<std::pair<LabelId, PropertyId>> ListIndices() const;
|
||||
|
||||
/// @throw std::bad_alloc if unable to copy a PropertyValue
|
||||
void RemoveObsoleteEntries(uint64_t oldest_active_start_timestamp);
|
||||
|
||||
|
@ -152,6 +152,18 @@ class VerticesIterable final {
|
||||
Iterator end();
|
||||
};
|
||||
|
||||
/// Structure used to return information about existing indices in the storage.
|
||||
struct IndicesInfo {
|
||||
std::vector<LabelId> label;
|
||||
std::vector<std::pair<LabelId, PropertyId>> label_property;
|
||||
};
|
||||
|
||||
/// Structure used to return information about existing constraints in the
|
||||
/// storage.
|
||||
struct ConstraintsInfo {
|
||||
std::vector<std::pair<LabelId, PropertyId>> existence;
|
||||
};
|
||||
|
||||
class Storage final {
|
||||
public:
|
||||
/// @throw std::system_error
|
||||
@ -321,6 +333,11 @@ class Storage final {
|
||||
return indices_.label_property_index.IndexExists(label, property);
|
||||
}
|
||||
|
||||
IndicesInfo ListAllIndices() const {
|
||||
return {indices_.label_index.ListIndices(),
|
||||
indices_.label_property_index.ListIndices()};
|
||||
}
|
||||
|
||||
/// Creates a unique constraint`. Returns true if the constraint was
|
||||
/// successfuly added, false if it already exists and an
|
||||
/// `ExistenceConstraintViolation` if there is an existing vertex violating
|
||||
@ -342,6 +359,10 @@ class Storage final {
|
||||
return ::storage::DropExistenceConstraint(&constraints_, label, property);
|
||||
}
|
||||
|
||||
ConstraintsInfo ListAllConstraints() const {
|
||||
return {ListExistenceConstraints(constraints_)};
|
||||
}
|
||||
|
||||
private:
|
||||
/// @throw std::system_error
|
||||
/// @throw std::bad_alloc
|
||||
|
@ -6,6 +6,8 @@
|
||||
// NOLINTNEXTLINE(google-build-using-namespace)
|
||||
using namespace storage;
|
||||
|
||||
using testing::UnorderedElementsAre;
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define ASSERT_NO_ERROR(result) ASSERT_FALSE((result).HasError())
|
||||
|
||||
@ -31,26 +33,39 @@ class ConstraintsTest : public testing::Test {
|
||||
|
||||
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
||||
TEST_F(ConstraintsTest, CreateAndDrop) {
|
||||
EXPECT_EQ(storage.ListAllConstraints().existence.size(), 0);
|
||||
{
|
||||
auto res = storage.CreateExistenceConstraint(label1, prop1);
|
||||
EXPECT_TRUE(res.HasValue() && res.GetValue());
|
||||
}
|
||||
EXPECT_THAT(storage.ListAllConstraints().existence,
|
||||
UnorderedElementsAre(std::make_pair(label1, prop1)));
|
||||
{
|
||||
auto res = storage.CreateExistenceConstraint(label1, prop1);
|
||||
EXPECT_TRUE(res.HasValue() && !res.GetValue());
|
||||
}
|
||||
EXPECT_THAT(storage.ListAllConstraints().existence,
|
||||
UnorderedElementsAre(std::make_pair(label1, prop1)));
|
||||
{
|
||||
auto res = storage.CreateExistenceConstraint(label2, prop1);
|
||||
EXPECT_TRUE(res.HasValue() && res.GetValue());
|
||||
}
|
||||
EXPECT_THAT(storage.ListAllConstraints().existence,
|
||||
UnorderedElementsAre(std::make_pair(label1, prop1),
|
||||
std::make_pair(label2, prop1)));
|
||||
EXPECT_TRUE(storage.DropExistenceConstraint(label1, prop1));
|
||||
EXPECT_FALSE(storage.DropExistenceConstraint(label1, prop1));
|
||||
EXPECT_THAT(storage.ListAllConstraints().existence,
|
||||
UnorderedElementsAre(std::make_pair(label2, prop1)));
|
||||
EXPECT_TRUE(storage.DropExistenceConstraint(label2, prop1));
|
||||
EXPECT_FALSE(storage.DropExistenceConstraint(label2, prop2));
|
||||
EXPECT_EQ(storage.ListAllConstraints().existence.size(), 0);
|
||||
{
|
||||
auto res = storage.CreateExistenceConstraint(label2, prop1);
|
||||
EXPECT_TRUE(res.HasValue() && res.GetValue());
|
||||
}
|
||||
EXPECT_THAT(storage.ListAllConstraints().existence,
|
||||
UnorderedElementsAre(std::make_pair(label2, prop1)));
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
||||
|
@ -6,9 +6,6 @@
|
||||
// NOLINTNEXTLINE(google-build-using-namespace)
|
||||
using namespace storage;
|
||||
|
||||
LabelId nil_label = LabelId::FromUint(0);
|
||||
PropertyId nil_property = PropertyId::FromUint(0);
|
||||
|
||||
using testing::IsEmpty;
|
||||
using testing::UnorderedElementsAre;
|
||||
|
||||
@ -17,12 +14,6 @@ using testing::UnorderedElementsAre;
|
||||
|
||||
class IndexTest : public testing::Test {
|
||||
protected:
|
||||
IndexTest()
|
||||
: prop_id(nil_property),
|
||||
prop_val(nil_property),
|
||||
label1(nil_label),
|
||||
label2(nil_label) {}
|
||||
|
||||
void SetUp() override {
|
||||
auto acc = storage.Access();
|
||||
prop_id = acc.NameToProperty("id");
|
||||
@ -67,10 +58,13 @@ TEST_F(IndexTest, LabelIndexBasic) {
|
||||
// vertices.
|
||||
// 4. Delete even numbered vertices.
|
||||
auto acc = storage.Access();
|
||||
EXPECT_EQ(storage.ListAllIndices().label.size(), 0);
|
||||
EXPECT_THAT(GetIds(acc.Vertices(label1, View::OLD), View::OLD), IsEmpty());
|
||||
EXPECT_THAT(GetIds(acc.Vertices(label2, View::OLD), View::OLD), IsEmpty());
|
||||
EXPECT_THAT(GetIds(acc.Vertices(label1, View::NEW), View::NEW), IsEmpty());
|
||||
EXPECT_THAT(GetIds(acc.Vertices(label2, View::NEW), View::NEW), IsEmpty());
|
||||
EXPECT_THAT(storage.ListAllIndices().label,
|
||||
UnorderedElementsAre(label1, label2));
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
auto vertex = CreateVertex(&acc);
|
||||
@ -220,20 +214,31 @@ TEST_F(IndexTest, LabelIndexCountEstimate) {
|
||||
|
||||
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
||||
TEST_F(IndexTest, LabelPropertyIndexCreateAndDrop) {
|
||||
EXPECT_EQ(storage.ListAllIndices().label_property.size(), 0);
|
||||
EXPECT_TRUE(storage.CreateIndex(label1, prop_id));
|
||||
EXPECT_TRUE(storage.LabelPropertyIndexExists(label1, prop_id));
|
||||
EXPECT_THAT(storage.ListAllIndices().label_property,
|
||||
UnorderedElementsAre(std::make_pair(label1, prop_id)));
|
||||
EXPECT_FALSE(storage.LabelPropertyIndexExists(label2, prop_id));
|
||||
EXPECT_FALSE(storage.CreateIndex(label1, prop_id));
|
||||
EXPECT_THAT(storage.ListAllIndices().label_property,
|
||||
UnorderedElementsAre(std::make_pair(label1, prop_id)));
|
||||
|
||||
EXPECT_TRUE(storage.CreateIndex(label2, prop_id));
|
||||
EXPECT_TRUE(storage.LabelPropertyIndexExists(label2, prop_id));
|
||||
EXPECT_THAT(storage.ListAllIndices().label_property,
|
||||
UnorderedElementsAre(std::make_pair(label1, prop_id),
|
||||
std::make_pair(label2, prop_id)));
|
||||
|
||||
EXPECT_TRUE(storage.DropIndex(label1, prop_id));
|
||||
EXPECT_FALSE(storage.LabelPropertyIndexExists(label1, prop_id));
|
||||
EXPECT_THAT(storage.ListAllIndices().label_property,
|
||||
UnorderedElementsAre(std::make_pair(label2, prop_id)));
|
||||
EXPECT_FALSE(storage.DropIndex(label1, prop_id));
|
||||
|
||||
EXPECT_TRUE(storage.DropIndex(label2, prop_id));
|
||||
EXPECT_FALSE(storage.LabelPropertyIndexExists(label2, prop_id));
|
||||
EXPECT_EQ(storage.ListAllIndices().label_property.size(), 0);
|
||||
}
|
||||
|
||||
// The following three tests are almost an exact copy-paste of the corresponding
|
||||
|
Loading…
Reference in New Issue
Block a user