Remove unique from label-prop index
Summary: Remove unique feature from label-property index Reviewers: ipaljak, mferencevic, vkasljevic Reviewed By: mferencevic Subscribers: tsabolcec, pullbot Differential Revision: https://phabricator.memgraph.io/D2045
This commit is contained in:
parent
1f93edaa88
commit
f2cc41fa59
@ -147,7 +147,7 @@ class WorkerAccessor final : public GraphDbAccessor {
|
||||
WorkerAccessor(Worker *db, tx::TransactionId tx_id)
|
||||
: GraphDbAccessor(*db, tx_id) {}
|
||||
|
||||
void BuildIndex(storage::Label, storage::Property, bool) override {
|
||||
void BuildIndex(storage::Label, storage::Property) override {
|
||||
// TODO: Rethink BuildIndex API or inheritance. It's rather strange that a
|
||||
// derived type blocks this functionality.
|
||||
LOG(FATAL) << "BuildIndex invoked on worker.";
|
||||
|
@ -132,10 +132,8 @@ EdgeAccessor GraphDbAccessor::FindEdge(gid::Gid gid, bool current_state) {
|
||||
}
|
||||
|
||||
void GraphDbAccessor::BuildIndex(storage::Label label,
|
||||
storage::Property property,
|
||||
bool unique) {
|
||||
storage::Property property) {
|
||||
DCHECK(!commited_ && !aborted_) << "Accessor committed or aborted";
|
||||
if (unique) throw utils::NotYetImplemented("Distributed unique index");
|
||||
db_.storage().index_build_tx_in_progress_.access().insert(transaction_.id_);
|
||||
|
||||
// on function exit remove the create index transaction from
|
||||
|
@ -467,8 +467,7 @@ class GraphDbAccessor {
|
||||
* @param label - label to build for
|
||||
* @param property - property to build for
|
||||
*/
|
||||
virtual void BuildIndex(storage::Label label, storage::Property property,
|
||||
bool);
|
||||
virtual void BuildIndex(storage::Label label, storage::Property property);
|
||||
|
||||
/// Deletes the index responisble for (label, property).
|
||||
/// At the moment this isn't implemented in distributed.
|
||||
|
@ -115,9 +115,7 @@ void DumpEdge(std::ostream *os, GraphDbAccessor *dba,
|
||||
|
||||
void DumpIndexKey(std::ostream *os, GraphDbAccessor *dba,
|
||||
const LabelPropertyIndex::Key &key) {
|
||||
*os << "CREATE ";
|
||||
if (key.unique_) *os << "UNIQUE ";
|
||||
*os << "INDEX ON :" << dba->LabelName(key.label_) << "("
|
||||
*os << "CREATE INDEX ON :" << dba->LabelName(key.label_) << "("
|
||||
<< dba->PropertyName(key.property_) << ");";
|
||||
}
|
||||
|
||||
|
@ -138,11 +138,11 @@ EdgeAccessor GraphDbAccessor::FindEdge(gid::Gid gid, bool current_state) {
|
||||
}
|
||||
|
||||
void GraphDbAccessor::BuildIndex(storage::Label label,
|
||||
storage::Property property, bool unique) {
|
||||
storage::Property property) {
|
||||
DCHECK(!commited_ && !aborted_) << "Accessor committed or aborted";
|
||||
|
||||
// Create the index
|
||||
const LabelPropertyIndex::Key key(label, property, unique);
|
||||
const LabelPropertyIndex::Key key(label, property);
|
||||
if (db_->storage().label_property_index_.CreateIndex(key) == false) {
|
||||
throw IndexExistsException(
|
||||
"Index is either being created by another transaction or already "
|
||||
@ -155,9 +155,6 @@ void GraphDbAccessor::BuildIndex(storage::Label label,
|
||||
dba.PopulateIndex(key);
|
||||
dba.EnableIndex(key);
|
||||
dba.Commit();
|
||||
} catch (const ConstraintViolationException &) {
|
||||
db_->storage().label_property_index_.DeleteIndex(key);
|
||||
throw;
|
||||
} catch (const tx::TransactionEngineError &e) {
|
||||
db_->storage().label_property_index_.DeleteIndex(key);
|
||||
throw TransactionException(e.what());
|
||||
@ -171,18 +168,15 @@ void GraphDbAccessor::EnableIndex(const LabelPropertyIndex::Key &key) {
|
||||
// reason.
|
||||
wal().Emplace(database::StateDelta::BuildIndex(
|
||||
transaction_id(), key.label_, LabelName(key.label_), key.property_,
|
||||
PropertyName(key.property_), key.unique_));
|
||||
PropertyName(key.property_)));
|
||||
}
|
||||
|
||||
void GraphDbAccessor::PopulateIndex(const LabelPropertyIndex::Key &key) {
|
||||
for (auto vertex : Vertices(key.label_, false)) {
|
||||
if (vertex.PropsAt(key.property_).type() == PropertyValue::Type::Null)
|
||||
continue;
|
||||
if (!db_->storage().label_property_index_.UpdateOnLabelProperty(
|
||||
vertex.address(), vertex.current_)) {
|
||||
throw ConstraintViolationException(
|
||||
"Index couldn't be created due to constraint violation!");
|
||||
}
|
||||
db_->storage().label_property_index_.UpdateOnLabelProperty(vertex.address(),
|
||||
vertex.current_);
|
||||
}
|
||||
}
|
||||
|
||||
@ -300,12 +294,7 @@ void GraphDbAccessor::UpdateOnAddLabel(storage::Label label,
|
||||
throw ConstraintViolationException(e.what());
|
||||
}
|
||||
|
||||
if (!db_->storage().label_property_index_.UpdateOnLabel(label, vlist_ptr,
|
||||
vertex)) {
|
||||
throw ConstraintViolationException(
|
||||
"Node couldn't be updated due to index constraint violation!");
|
||||
}
|
||||
|
||||
db_->storage().label_property_index_.UpdateOnLabel(label, vlist_ptr, vertex);
|
||||
db_->storage().labels_index_.Update(label, vlist_ptr, vertex);
|
||||
}
|
||||
|
||||
@ -330,11 +319,8 @@ void GraphDbAccessor::UpdateOnAddProperty(
|
||||
throw ConstraintViolationException(e.what());
|
||||
}
|
||||
|
||||
if (!db_->storage().label_property_index_.UpdateOnProperty(
|
||||
property, vertex_accessor.address(), vertex)) {
|
||||
throw ConstraintViolationException(
|
||||
"Node couldn't be updated due to unique index violation!");
|
||||
}
|
||||
db_->storage().label_property_index_.UpdateOnProperty(
|
||||
property, vertex_accessor.address(), vertex);
|
||||
}
|
||||
|
||||
void GraphDbAccessor::UpdateOnRemoveProperty(
|
||||
@ -552,9 +538,8 @@ std::vector<std::string> GraphDbAccessor::IndexInfo() const {
|
||||
}
|
||||
for (LabelPropertyIndex::Key key :
|
||||
db_->storage().label_property_index_.Keys()) {
|
||||
info.emplace_back(fmt::format(":{}({}){}", LabelName(key.label_),
|
||||
PropertyName(key.property_),
|
||||
key.unique_ ? " unique" : ""));
|
||||
info.emplace_back(fmt::format(":{}({})", LabelName(key.label_),
|
||||
PropertyName(key.property_)));
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
@ -411,8 +411,7 @@ class GraphDbAccessor {
|
||||
* @param label - label to build for
|
||||
* @param property - property to build for
|
||||
*/
|
||||
void BuildIndex(storage::Label label, storage::Property property,
|
||||
bool unique);
|
||||
void BuildIndex(storage::Label label, storage::Property property);
|
||||
|
||||
/// Deletes the index responisble for (label, property).
|
||||
///
|
||||
|
@ -138,11 +138,11 @@ EdgeAccessor GraphDbAccessor::FindEdge(gid::Gid gid, bool current_state) {
|
||||
}
|
||||
|
||||
void GraphDbAccessor::BuildIndex(storage::Label label,
|
||||
storage::Property property, bool unique) {
|
||||
storage::Property property) {
|
||||
DCHECK(!commited_ && !aborted_) << "Accessor committed or aborted";
|
||||
|
||||
// Create the index
|
||||
const LabelPropertyIndex::Key key(label, property, unique);
|
||||
const LabelPropertyIndex::Key key(label, property);
|
||||
if (db_->storage().label_property_index_.CreateIndex(key) == false) {
|
||||
throw IndexExistsException(
|
||||
"Index is either being created by another transaction or already "
|
||||
@ -155,9 +155,6 @@ void GraphDbAccessor::BuildIndex(storage::Label label,
|
||||
dba.PopulateIndex(key);
|
||||
dba.EnableIndex(key);
|
||||
dba.Commit();
|
||||
} catch (const ConstraintViolationException &) {
|
||||
db_->storage().label_property_index_.DeleteIndex(key);
|
||||
throw;
|
||||
} catch (const tx::TransactionEngineError &e) {
|
||||
db_->storage().label_property_index_.DeleteIndex(key);
|
||||
throw TransactionException(e.what());
|
||||
@ -170,18 +167,15 @@ void GraphDbAccessor::EnableIndex(const LabelPropertyIndex::Key &key) {
|
||||
// built at this point even if this DBA's transaction aborts for some reason.
|
||||
raft()->Emplace(database::StateDelta::BuildIndex(
|
||||
transaction_id(), key.label_, LabelName(key.label_), key.property_,
|
||||
PropertyName(key.property_), key.unique_));
|
||||
PropertyName(key.property_)));
|
||||
}
|
||||
|
||||
void GraphDbAccessor::PopulateIndex(const LabelPropertyIndex::Key &key) {
|
||||
for (auto vertex : Vertices(key.label_, false)) {
|
||||
if (vertex.PropsAt(key.property_).type() == PropertyValue::Type::Null)
|
||||
continue;
|
||||
if (!db_->storage().label_property_index_.UpdateOnLabelProperty(
|
||||
vertex.address(), vertex.current_)) {
|
||||
throw ConstraintViolationException(
|
||||
"Index couldn't be created due to constraint violation!");
|
||||
}
|
||||
db_->storage().label_property_index_.UpdateOnLabelProperty(vertex.address(),
|
||||
vertex.current_);
|
||||
}
|
||||
}
|
||||
|
||||
@ -210,11 +204,7 @@ void GraphDbAccessor::UpdateLabelIndices(storage::Label label,
|
||||
DCHECK(!commited_ && !aborted_) << "Accessor committed or aborted";
|
||||
auto *vlist_ptr = vertex_accessor.address();
|
||||
|
||||
if (!db_->storage().label_property_index_.UpdateOnLabel(label, vlist_ptr,
|
||||
vertex)) {
|
||||
throw ConstraintViolationException(
|
||||
"Node couldn't be updated due to index constraint violation!");
|
||||
}
|
||||
db_->storage().label_property_index_.UpdateOnLabel(label, vlist_ptr, vertex);
|
||||
db_->storage().labels_index_.Update(label, vlist_ptr, vertex);
|
||||
}
|
||||
|
||||
@ -222,11 +212,8 @@ void GraphDbAccessor::UpdatePropertyIndex(
|
||||
storage::Property property, const RecordAccessor<Vertex> &vertex_accessor,
|
||||
const Vertex *const vertex) {
|
||||
DCHECK(!commited_ && !aborted_) << "Accessor committed or aborted";
|
||||
if (!db_->storage().label_property_index_.UpdateOnProperty(
|
||||
property, vertex_accessor.address(), vertex)) {
|
||||
throw ConstraintViolationException(
|
||||
"Node couldn't be updated due to index constraint violation!");
|
||||
}
|
||||
db_->storage().label_property_index_.UpdateOnProperty(
|
||||
property, vertex_accessor.address(), vertex);
|
||||
}
|
||||
|
||||
int64_t GraphDbAccessor::VerticesCount() const {
|
||||
@ -427,9 +414,8 @@ std::vector<std::string> GraphDbAccessor::IndexInfo() const {
|
||||
}
|
||||
for (LabelPropertyIndex::Key key :
|
||||
db_->storage().label_property_index_.Keys()) {
|
||||
info.emplace_back(fmt::format(":{}({}){}", LabelName(key.label_),
|
||||
PropertyName(key.property_),
|
||||
key.unique_ ? " unique" : ""));
|
||||
info.emplace_back(fmt::format(":{}({})", LabelName(key.label_),
|
||||
PropertyName(key.property_)));
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
@ -418,8 +418,7 @@ class GraphDbAccessor {
|
||||
* @param label - label to build for
|
||||
* @param property - property to build for
|
||||
*/
|
||||
void BuildIndex(storage::Label label, storage::Property property,
|
||||
bool unique);
|
||||
void BuildIndex(storage::Label label, storage::Property property);
|
||||
|
||||
/// Deletes the index responisble for (label, property).
|
||||
///
|
||||
|
@ -142,12 +142,10 @@ bool RecoverSnapshot(const fs::path &snapshot_file, database::GraphDb *db,
|
||||
auto label = *it++;
|
||||
RETURN_IF_NOT(it != index_value.end());
|
||||
auto property = *it++;
|
||||
RETURN_IF_NOT(it != index_value.end());
|
||||
auto unique = *it++;
|
||||
RETURN_IF_NOT(label.IsString() && property.IsString() && unique.IsBool());
|
||||
RETURN_IF_NOT(label.IsString() && property.IsString());
|
||||
recovery_data->indexes.emplace_back(
|
||||
IndexRecoveryData{label.ValueString(), property.ValueString(),
|
||||
/*create = */ true, unique.ValueBool()});
|
||||
/*create = */ true});
|
||||
}
|
||||
|
||||
// Read a list of unique constraints
|
||||
@ -450,7 +448,7 @@ void RecoverWal(const fs::path &durability_dir, database::GraphDb *db,
|
||||
} else {
|
||||
recovery_data->indexes.emplace_back(
|
||||
IndexRecoveryData{delta.label_name, delta.property_name,
|
||||
/*create = */ true, delta.unique});
|
||||
/*create = */ true});
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -537,7 +535,7 @@ void RecoverIndexes(database::GraphDb *db,
|
||||
auto label = dba.Label(index.label);
|
||||
auto property = dba.Property(index.property);
|
||||
if (index.create) {
|
||||
dba.BuildIndex(label, property, index.unique);
|
||||
dba.BuildIndex(label, property);
|
||||
} else {
|
||||
dba.DeleteIndex(label, property);
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ namespace fs = std::filesystem;
|
||||
namespace durability {
|
||||
|
||||
// Snapshot layout is described in durability/version.hpp
|
||||
static_assert(durability::kVersion == 10,
|
||||
static_assert(durability::kVersion == 11,
|
||||
"Wrong snapshot version, please update!");
|
||||
|
||||
namespace {
|
||||
@ -50,7 +50,6 @@ bool Encode(const fs::path &snapshot_file, database::GraphDb &db,
|
||||
for (const auto &key : dba.GetIndicesKeys()) {
|
||||
index_vec.emplace_back(dba.LabelName(key.label_));
|
||||
index_vec.emplace_back(dba.PropertyName(key.property_));
|
||||
index_vec.emplace_back(key.unique_);
|
||||
}
|
||||
encoder.WriteList(index_vec);
|
||||
}
|
||||
|
@ -103,14 +103,12 @@ StateDelta StateDelta::RemoveEdge(tx::TransactionId tx_id, gid::Gid edge_id) {
|
||||
StateDelta StateDelta::BuildIndex(tx::TransactionId tx_id, storage::Label label,
|
||||
const std::string &label_name,
|
||||
storage::Property property,
|
||||
const std::string &property_name,
|
||||
bool unique) {
|
||||
const std::string &property_name) {
|
||||
StateDelta op(StateDelta::Type::BUILD_INDEX, tx_id);
|
||||
op.label = label;
|
||||
op.label_name = label_name;
|
||||
op.property = property;
|
||||
op.property_name = property_name;
|
||||
op.unique = unique;
|
||||
return op;
|
||||
}
|
||||
|
||||
@ -202,7 +200,6 @@ void StateDelta::Encode(
|
||||
encoder.WriteString(label_name);
|
||||
encoder.WriteInt(property.Id());
|
||||
encoder.WriteString(property_name);
|
||||
encoder.WriteBool(unique);
|
||||
break;
|
||||
case Type::DROP_INDEX:
|
||||
encoder.WriteInt(label.Id());
|
||||
@ -305,7 +302,6 @@ std::optional<StateDelta> StateDelta::Decode(
|
||||
DECODE_MEMBER(label_name, ValueString)
|
||||
DECODE_MEMBER_CAST(property, ValueInt, storage::Property)
|
||||
DECODE_MEMBER(property_name, ValueString)
|
||||
DECODE_MEMBER(unique, ValueBool)
|
||||
break;
|
||||
case Type::DROP_INDEX:
|
||||
DECODE_MEMBER_CAST(label, ValueInt, storage::Label)
|
||||
|
@ -45,8 +45,7 @@ cpp<#
|
||||
(value "PropertyValue" :initval "PropertyValue::Null")
|
||||
(label "storage::Label")
|
||||
(label-name "std::string")
|
||||
(check-empty :bool)
|
||||
(unique :bool))
|
||||
(check-empty :bool))
|
||||
(:documentation
|
||||
"Describes single change to the database state. Used for durability (WAL).
|
||||
|
||||
@ -71,7 +70,7 @@ in StateDeltas.")
|
||||
remove-label ;; vertex_id, label, label_name
|
||||
remove-vertex ;; vertex_id, check_empty
|
||||
remove-edge ;; edge_id
|
||||
build-index ;; label, label_name, property, property_name, unique
|
||||
build-index ;; label, label_name, property, property_name
|
||||
drop-index ;; label, label_name, property, property_name
|
||||
build-unique_constraint ;; label, label_name, properties, property_names
|
||||
drop-unique_constraint ;; label, label_name, properties, property_names
|
||||
@ -128,7 +127,7 @@ omitted in the comment."))
|
||||
static StateDelta BuildIndex(tx::TransactionId tx_id, storage::Label label,
|
||||
const std::string &label_name,
|
||||
storage::Property property,
|
||||
const std::string &property_name, bool unique);
|
||||
const std::string &property_name);
|
||||
static StateDelta DropIndex(tx::TransactionId tx_id, storage::Label label,
|
||||
const std::string &label_name,
|
||||
storage::Property property,
|
||||
|
@ -15,7 +15,7 @@ constexpr std::array<uint8_t, 4> kSnapshotMagic{{'M', 'G', 's', 'n'}};
|
||||
constexpr std::array<uint8_t, 4> kWalMagic{{'M', 'G', 'w', 'l'}};
|
||||
|
||||
// The current default version of snapshot and WAL encoding / decoding.
|
||||
constexpr int64_t kVersion{10};
|
||||
constexpr int64_t kVersion{11};
|
||||
|
||||
// Snapshot format (version 10):
|
||||
// 1) Magic number + snapshot version
|
||||
|
@ -71,12 +71,10 @@ bool RecoverSnapshot(const fs::path &snapshot_file, database::GraphDb *db,
|
||||
auto label = *it++;
|
||||
RETURN_IF_NOT(it != index_value.end());
|
||||
auto property = *it++;
|
||||
RETURN_IF_NOT(it != index_value.end());
|
||||
auto unique = *it++;
|
||||
RETURN_IF_NOT(label.IsString() && property.IsString() && unique.IsBool());
|
||||
RETURN_IF_NOT(label.IsString() && property.IsString());
|
||||
recovery_data->indexes.emplace_back(
|
||||
IndexRecoveryData{label.ValueString(), property.ValueString(),
|
||||
/*create = */ true, unique.ValueBool()});
|
||||
/*create = */ true});
|
||||
}
|
||||
|
||||
auto dba = db->Access();
|
||||
@ -162,7 +160,7 @@ void RecoverIndexes(database::GraphDb *db,
|
||||
auto label = dba.Label(index.label);
|
||||
auto property = dba.Property(index.property);
|
||||
if (index.create) {
|
||||
dba.BuildIndex(label, property, index.unique);
|
||||
dba.BuildIndex(label, property);
|
||||
} else {
|
||||
dba.DeleteIndex(label, property);
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ namespace fs = std::filesystem;
|
||||
namespace durability {
|
||||
|
||||
// Snapshot layout is described in durability/version.hpp
|
||||
static_assert(durability::kVersion == 8,
|
||||
static_assert(durability::kVersion == 9,
|
||||
"Wrong snapshot version, please update!");
|
||||
|
||||
namespace {
|
||||
@ -38,7 +38,6 @@ bool Encode(const fs::path &snapshot_file, database::GraphDb &db,
|
||||
for (const auto &key : dba.GetIndicesKeys()) {
|
||||
index_vec.emplace_back(dba.LabelName(key.label_));
|
||||
index_vec.emplace_back(dba.PropertyName(key.property_));
|
||||
index_vec.emplace_back(key.unique_);
|
||||
}
|
||||
encoder.WriteList(index_vec);
|
||||
}
|
||||
|
@ -103,14 +103,12 @@ StateDelta StateDelta::RemoveEdge(tx::TransactionId tx_id, gid::Gid edge_id) {
|
||||
StateDelta StateDelta::BuildIndex(tx::TransactionId tx_id, storage::Label label,
|
||||
const std::string &label_name,
|
||||
storage::Property property,
|
||||
const std::string &property_name,
|
||||
bool unique) {
|
||||
const std::string &property_name) {
|
||||
StateDelta op(StateDelta::Type::BUILD_INDEX, tx_id);
|
||||
op.label = label;
|
||||
op.label_name = label_name;
|
||||
op.property = property;
|
||||
op.property_name = property_name;
|
||||
op.unique = unique;
|
||||
return op;
|
||||
}
|
||||
|
||||
@ -182,7 +180,6 @@ void StateDelta::Encode(
|
||||
encoder.WriteString(label_name);
|
||||
encoder.WriteInt(property.Id());
|
||||
encoder.WriteString(property_name);
|
||||
encoder.WriteBool(unique);
|
||||
break;
|
||||
case Type::DROP_INDEX:
|
||||
encoder.WriteInt(label.Id());
|
||||
@ -264,7 +261,6 @@ std::optional<StateDelta> StateDelta::Decode(
|
||||
DECODE_MEMBER(label_name, ValueString)
|
||||
DECODE_MEMBER_CAST(property, ValueInt, storage::Property)
|
||||
DECODE_MEMBER(property_name, ValueString)
|
||||
DECODE_MEMBER(unique, ValueBool)
|
||||
break;
|
||||
case Type::DROP_INDEX:
|
||||
DECODE_MEMBER_CAST(label, ValueInt, storage::Label)
|
||||
@ -337,8 +333,7 @@ void StateDelta::Apply(GraphDbAccessor &dba) const {
|
||||
break;
|
||||
}
|
||||
case Type::BUILD_INDEX: {
|
||||
dba.BuildIndex(dba.Label(label_name), dba.Property(property_name),
|
||||
unique);
|
||||
dba.BuildIndex(dba.Label(label_name), dba.Property(property_name));
|
||||
break;
|
||||
}
|
||||
case Type::DROP_INDEX: {
|
||||
|
@ -38,8 +38,7 @@ cpp<#
|
||||
(value "PropertyValue" :initval "PropertyValue::Null")
|
||||
(label "storage::Label")
|
||||
(label-name "std::string")
|
||||
(check-empty :bool)
|
||||
(unique :bool))
|
||||
(check-empty :bool))
|
||||
(:documentation
|
||||
"Describes single change to the database state. Used for state communication
|
||||
over network in HA.
|
||||
@ -65,7 +64,7 @@ in StateDeltas.")
|
||||
remove-label ;; vertex_id, label, label_name
|
||||
remove-vertex ;; vertex_id, check_empty
|
||||
remove-edge ;; edge_id
|
||||
build-index ;; label, label_name, property, property_name, unique
|
||||
build-index ;; label, label_name, property, property_name
|
||||
drop-index ;; label, label_name, property, property_name
|
||||
no-op ;; no-op state delta required by Raft protocol
|
||||
)
|
||||
@ -122,7 +121,7 @@ omitted in the comment.")
|
||||
static StateDelta BuildIndex(tx::TransactionId tx_id, storage::Label label,
|
||||
const std::string &label_name,
|
||||
storage::Property property,
|
||||
const std::string &property_name, bool unique);
|
||||
const std::string &property_name);
|
||||
static StateDelta DropIndex(tx::TransactionId tx_id, storage::Label label,
|
||||
const std::string &label_name,
|
||||
storage::Property property,
|
||||
|
@ -14,9 +14,9 @@ namespace durability {
|
||||
constexpr std::array<uint8_t, 6> kSnapshotMagic{{'M', 'G', 'H', 'A', 's', 'n'}};
|
||||
|
||||
// The current default version of snapshot and WAL encoding / decoding.
|
||||
constexpr int64_t kVersion{8};
|
||||
constexpr int64_t kVersion{9};
|
||||
|
||||
// Snapshot format (version 8):
|
||||
// Snapshot format (version 9):
|
||||
// 1) Magic number + snapshot version
|
||||
//
|
||||
// 2) A list of label+property indices.
|
||||
|
@ -547,22 +547,24 @@ Callback HandleIndexQuery(IndexQuery *index_query,
|
||||
|
||||
Callback callback;
|
||||
switch (index_query->action_) {
|
||||
case IndexQuery::Action::CREATE:
|
||||
case IndexQuery::Action::CREATE_UNIQUE:
|
||||
#ifdef MG_SINGLE_NODE
|
||||
throw QueryRuntimeException(
|
||||
"Unique index is not supported, use unique constraint instead ");
|
||||
#else
|
||||
throw QueryRuntimeException("Unique index is not supported");
|
||||
#endif
|
||||
case IndexQuery::Action::CREATE:
|
||||
callback.fn = [action, label, properties, db_accessor,
|
||||
invalidate_plan_cache] {
|
||||
try {
|
||||
CHECK(properties.size() == 1);
|
||||
db_accessor->BuildIndex(label, properties[0],
|
||||
action == IndexQuery::Action::CREATE_UNIQUE);
|
||||
db_accessor->BuildIndex(label, properties[0]);
|
||||
invalidate_plan_cache();
|
||||
} catch (const database::ConstraintViolationException &e) {
|
||||
throw QueryRuntimeException(e.what());
|
||||
} catch (const database::IndexExistsException &e) {
|
||||
if (action == IndexQuery::Action::CREATE_UNIQUE) {
|
||||
throw QueryRuntimeException(e.what());
|
||||
}
|
||||
// Otherwise ignore creating an existing index.
|
||||
// Ignore creating an existing index.
|
||||
} catch (const database::TransactionException &e) {
|
||||
throw QueryRuntimeException(e.what());
|
||||
}
|
||||
|
@ -38,14 +38,10 @@ class LabelPropertyIndex {
|
||||
public:
|
||||
const storage::Label label_;
|
||||
const storage::Property property_;
|
||||
bool unique_{false};
|
||||
|
||||
Key(storage::Label label, storage::Property property)
|
||||
: label_(label), property_(property) {}
|
||||
|
||||
Key(storage::Label label, storage::Property property, bool unique)
|
||||
: label_(label), property_(property), unique_(unique) {}
|
||||
|
||||
// Comparison operators - we need them to keep this sorted inside skiplist.
|
||||
bool operator<(const Key &other) const {
|
||||
if (this->label_ != other.label_) return this->label_ < other.label_;
|
||||
@ -77,37 +73,16 @@ class LabelPropertyIndex {
|
||||
*/
|
||||
void DeleteIndex(const Key &key) { indices_.access().remove(key); }
|
||||
|
||||
/** NOTE: All update methods aren't supporting the case where two threads
|
||||
* try to update the index with the same value. If both of them conclude that
|
||||
* the insert is valid, one will insert first and that makes the second insert
|
||||
* invalid if the unique constraint set.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief - Updates all indexes which should contain this vertex.
|
||||
* @param vlist - pointer to vlist entry to add
|
||||
* @param vertex - pointer to vertex record entry to add (contained in vlist)
|
||||
*/
|
||||
bool UpdateOnLabelProperty(mvcc::VersionList<Vertex> *const vlist,
|
||||
void UpdateOnLabelProperty(mvcc::VersionList<Vertex> *const vlist,
|
||||
const Vertex *const vertex) {
|
||||
const auto &labels = vertex->labels_;
|
||||
// We need to check if the given vertex can be inserted in all indexes
|
||||
auto access = indices_.access();
|
||||
for (auto &index : access) {
|
||||
if (!index.first.unique_) continue;
|
||||
// Vertex has the given label
|
||||
if (std::find(labels.begin(), labels.end(), index.first.label_) ==
|
||||
labels.end())
|
||||
continue;
|
||||
auto prop = vertex->properties_.at(index.first.property_);
|
||||
if (prop.type() != PropertyValue::Type::Null) {
|
||||
if (!CheckUniqueConstraint(*index.second, prop, vlist, vertex)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &index : access) {
|
||||
for (auto &index : indices_.access()) {
|
||||
// Vertex has the given label
|
||||
if (std::find(labels.begin(), labels.end(), index.first.label_) ==
|
||||
labels.end())
|
||||
@ -117,7 +92,6 @@ class LabelPropertyIndex {
|
||||
Insert(*index.second, prop, vlist, vertex);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -128,23 +102,11 @@ class LabelPropertyIndex {
|
||||
* @param vlist - pointer to vlist entry to add
|
||||
* @param vertex - pointer to vertex record entry to add (contained in vlist)
|
||||
*/
|
||||
bool UpdateOnLabel(storage::Label label,
|
||||
void UpdateOnLabel(storage::Label label,
|
||||
mvcc::VersionList<Vertex> *const vlist,
|
||||
const Vertex *const vertex) {
|
||||
// We need to check if the given vertex can be inserted in all indexes
|
||||
auto access = indices_.access();
|
||||
for (auto &index : access) {
|
||||
if (!index.first.unique_) continue;
|
||||
if (index.first.label_ != label) continue;
|
||||
auto prop = vertex->properties_.at(index.first.property_);
|
||||
if (prop.type() != PropertyValue::Type::Null) {
|
||||
if (!CheckUniqueConstraint(*index.second, prop, vlist, vertex)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &index : access) {
|
||||
for (auto &index : indices_.access()) {
|
||||
if (index.first.label_ != label) continue;
|
||||
auto prop = vertex->properties_.at(index.first.property_);
|
||||
if (prop.type() != PropertyValue::Type::Null) {
|
||||
@ -152,7 +114,6 @@ class LabelPropertyIndex {
|
||||
Insert(*index.second, prop, vlist, vertex);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -163,28 +124,11 @@ class LabelPropertyIndex {
|
||||
* @param vlist - pointer to vlist entry to add
|
||||
* @param vertex - pointer to vertex record entry to add (contained in vlist)
|
||||
*/
|
||||
bool UpdateOnProperty(storage::Property property,
|
||||
void UpdateOnProperty(storage::Property property,
|
||||
mvcc::VersionList<Vertex> *const vlist,
|
||||
const Vertex *const vertex) {
|
||||
const auto &labels = vertex->labels_;
|
||||
|
||||
// We need to check if the given vertex can be inserted in all indexes
|
||||
auto access = indices_.access();
|
||||
for (auto &index : access) {
|
||||
if (!index.first.unique_) continue;
|
||||
if (index.first.property_ != property) continue;
|
||||
if (std::find(labels.begin(), labels.end(), index.first.label_) !=
|
||||
labels.end()) {
|
||||
// Label exists and vertex should be added to skiplist.
|
||||
if (!CheckUniqueConstraint(*index.second,
|
||||
vertex->properties_.at(property), vlist,
|
||||
vertex)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &index : access) {
|
||||
for (auto &index : indices_.access()) {
|
||||
if (index.first.property_ != property) continue;
|
||||
if (std::find(labels.begin(), labels.end(), index.first.label_) !=
|
||||
labels.end()) {
|
||||
@ -192,7 +136,6 @@ class LabelPropertyIndex {
|
||||
Insert(*index.second, vertex->properties_.at(property), vlist, vertex);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -526,35 +469,6 @@ class LabelPropertyIndex {
|
||||
const Vertex *const record_{nullptr};
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief - Check if an insert is valid due to the unique constraint
|
||||
* @param index - into which index to add
|
||||
* @param value - value which to add
|
||||
* @param vlist - pointer to vlist entry to add
|
||||
* @param vertex - pointer to vertex record entry to add (contained in
|
||||
* vlist)
|
||||
* @param unique - unique constraint on index
|
||||
* @return bool - true if valid, false otherwise
|
||||
*/
|
||||
bool CheckUniqueConstraint(SkipList<IndexEntry> &index,
|
||||
const PropertyValue &value,
|
||||
mvcc::VersionList<Vertex> *const vlist,
|
||||
const Vertex *const vertex) {
|
||||
auto access = index.access();
|
||||
auto it = access.find_or_larger(IndexEntry{value, nullptr, nullptr});
|
||||
|
||||
// If not found.
|
||||
if (it == access.end()) {
|
||||
return true;
|
||||
}
|
||||
// If not equal.
|
||||
if (IndexEntry::Less(it->value_, value) ||
|
||||
IndexEntry::Less(value, it->value_)) {
|
||||
return true;
|
||||
}
|
||||
return vlist->cypher_id() == it->vlist_->cypher_id();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief - Insert value, vlist, vertex into corresponding index (key) if
|
||||
* the index exists.
|
||||
@ -563,12 +477,10 @@ class LabelPropertyIndex {
|
||||
* @param vlist - pointer to vlist entry to add
|
||||
* @param vertex - pointer to vertex record entry to add (contained in
|
||||
* vlist)
|
||||
* @param unique - unique constraint on index
|
||||
*/
|
||||
void Insert(SkipList<IndexEntry> &index, const PropertyValue &value,
|
||||
mvcc::VersionList<Vertex> *const vlist,
|
||||
const Vertex *const vertex) {
|
||||
// Property exists and vertex should be added to skiplist.
|
||||
index.access().insert(IndexEntry{value, vlist, vertex});
|
||||
}
|
||||
|
||||
|
@ -38,14 +38,10 @@ class LabelPropertyIndex {
|
||||
public:
|
||||
const storage::Label label_;
|
||||
const storage::Property property_;
|
||||
bool unique_{false};
|
||||
|
||||
Key(storage::Label label, storage::Property property)
|
||||
: label_(label), property_(property) {}
|
||||
|
||||
Key(storage::Label label, storage::Property property, bool unique)
|
||||
: label_(label), property_(property), unique_(unique) {}
|
||||
|
||||
// Comparison operators - we need them to keep this sorted inside skiplist.
|
||||
bool operator<(const Key &other) const {
|
||||
if (this->label_ != other.label_) return this->label_ < other.label_;
|
||||
@ -75,41 +71,18 @@ class LabelPropertyIndex {
|
||||
/**
|
||||
* Returns if it succeeded in deleting the index and freeing the index memory
|
||||
*/
|
||||
void DeleteIndex(const Key &key) {
|
||||
indices_.access().remove(key);
|
||||
}
|
||||
|
||||
/** NOTE: All update methods aren't supporting the case where two threads
|
||||
* try to update the index with the same value. If both of them conclude that
|
||||
* the insert is valid, one will insert first and that makes the second insert
|
||||
* invalid if the unique constraint set.
|
||||
*/
|
||||
void DeleteIndex(const Key &key) { indices_.access().remove(key); }
|
||||
|
||||
/**
|
||||
* @brief - Updates all indexes which should contain this vertex.
|
||||
* @param vlist - pointer to vlist entry to add
|
||||
* @param vertex - pointer to vertex record entry to add (contained in vlist)
|
||||
*/
|
||||
bool UpdateOnLabelProperty(mvcc::VersionList<Vertex> *const vlist,
|
||||
void UpdateOnLabelProperty(mvcc::VersionList<Vertex> *const vlist,
|
||||
const Vertex *const vertex) {
|
||||
const auto &labels = vertex->labels_;
|
||||
// We need to check if the given vertex can be inserted in all indexes
|
||||
auto access = indices_.access();
|
||||
for (auto &index : access) {
|
||||
if (!index.first.unique_) continue;
|
||||
// Vertex has the given label
|
||||
if (std::find(labels.begin(), labels.end(), index.first.label_) ==
|
||||
labels.end())
|
||||
continue;
|
||||
auto prop = vertex->properties_.at(index.first.property_);
|
||||
if (prop.type() != PropertyValue::Type::Null) {
|
||||
if (!CheckUniqueConstraint(*index.second, prop, vlist, vertex)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &index : access) {
|
||||
for (auto &index : indices_.access()) {
|
||||
// Vertex has the given label
|
||||
if (std::find(labels.begin(), labels.end(), index.first.label_) ==
|
||||
labels.end())
|
||||
@ -119,7 +92,6 @@ class LabelPropertyIndex {
|
||||
Insert(*index.second, prop, vlist, vertex);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -130,23 +102,11 @@ class LabelPropertyIndex {
|
||||
* @param vlist - pointer to vlist entry to add
|
||||
* @param vertex - pointer to vertex record entry to add (contained in vlist)
|
||||
*/
|
||||
bool UpdateOnLabel(storage::Label label,
|
||||
void UpdateOnLabel(storage::Label label,
|
||||
mvcc::VersionList<Vertex> *const vlist,
|
||||
const Vertex *const vertex) {
|
||||
// We need to check if the given vertex can be inserted in all indexes
|
||||
auto access = indices_.access();
|
||||
for (auto &index : access) {
|
||||
if (!index.first.unique_) continue;
|
||||
if (index.first.label_ != label) continue;
|
||||
auto prop = vertex->properties_.at(index.first.property_);
|
||||
if (prop.type() != PropertyValue::Type::Null) {
|
||||
if (!CheckUniqueConstraint(*index.second, prop, vlist, vertex)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &index : access) {
|
||||
for (auto &index : indices_.access()) {
|
||||
if (index.first.label_ != label) continue;
|
||||
auto prop = vertex->properties_.at(index.first.property_);
|
||||
if (prop.type() != PropertyValue::Type::Null) {
|
||||
@ -154,7 +114,6 @@ class LabelPropertyIndex {
|
||||
Insert(*index.second, prop, vlist, vertex);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -165,28 +124,11 @@ class LabelPropertyIndex {
|
||||
* @param vlist - pointer to vlist entry to add
|
||||
* @param vertex - pointer to vertex record entry to add (contained in vlist)
|
||||
*/
|
||||
bool UpdateOnProperty(storage::Property property,
|
||||
void UpdateOnProperty(storage::Property property,
|
||||
mvcc::VersionList<Vertex> *const vlist,
|
||||
const Vertex *const vertex) {
|
||||
const auto &labels = vertex->labels_;
|
||||
|
||||
// We need to check if the given vertex can be inserted in all indexes
|
||||
auto access = indices_.access();
|
||||
for (auto &index : access) {
|
||||
if (!index.first.unique_) continue;
|
||||
if (index.first.property_ != property) continue;
|
||||
if (std::find(labels.begin(), labels.end(), index.first.label_) !=
|
||||
labels.end()) {
|
||||
// Label exists and vertex should be added to skiplist.
|
||||
if (!CheckUniqueConstraint(*index.second,
|
||||
vertex->properties_.at(property), vlist,
|
||||
vertex)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &index : access) {
|
||||
for (auto &index : indices_.access()) {
|
||||
if (index.first.property_ != property) continue;
|
||||
if (std::find(labels.begin(), labels.end(), index.first.label_) !=
|
||||
labels.end()) {
|
||||
@ -194,7 +136,6 @@ class LabelPropertyIndex {
|
||||
Insert(*index.second, vertex->properties_.at(property), vlist, vertex);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -528,35 +469,6 @@ class LabelPropertyIndex {
|
||||
const Vertex *const record_{nullptr};
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief - Check if an insert is valid due to the unique constraint
|
||||
* @param index - into which index to add
|
||||
* @param value - value which to add
|
||||
* @param vlist - pointer to vlist entry to add
|
||||
* @param vertex - pointer to vertex record entry to add (contained in
|
||||
* vlist)
|
||||
* @param unique - unique constraint on index
|
||||
* @return bool - true if valid, false otherwise
|
||||
*/
|
||||
bool CheckUniqueConstraint(SkipList<IndexEntry> &index,
|
||||
const PropertyValue &value,
|
||||
mvcc::VersionList<Vertex> *const vlist,
|
||||
const Vertex *const vertex) {
|
||||
auto access = index.access();
|
||||
auto it = access.find_or_larger(IndexEntry{value, nullptr, nullptr});
|
||||
|
||||
// If not found.
|
||||
if (it == access.end()) {
|
||||
return true;
|
||||
}
|
||||
// If not equal.
|
||||
if (IndexEntry::Less(it->value_, value) ||
|
||||
IndexEntry::Less(value, it->value_)) {
|
||||
return true;
|
||||
}
|
||||
return vlist->cypher_id() == it->vlist_->cypher_id();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief - Insert value, vlist, vertex into corresponding index (key) if
|
||||
* the index exists.
|
||||
@ -565,12 +477,10 @@ class LabelPropertyIndex {
|
||||
* @param vlist - pointer to vlist entry to add
|
||||
* @param vertex - pointer to vertex record entry to add (contained in
|
||||
* vlist)
|
||||
* @param unique - unique constraint on index
|
||||
*/
|
||||
void Insert(SkipList<IndexEntry> &index, const PropertyValue &value,
|
||||
mvcc::VersionList<Vertex> *const vlist,
|
||||
const Vertex *const vertex) {
|
||||
// Property exists and vertex should be added to skiplist.
|
||||
index.access().insert(IndexEntry{value, vlist, vertex});
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,7 @@ static auto CreateIndexedVertices(int index_count, int vertex_count,
|
||||
database::GraphDb &db) {
|
||||
auto label = db.Access().Label("label");
|
||||
auto prop = db.Access().Property("prop");
|
||||
db.Access().BuildIndex(label, prop, false);
|
||||
db.Access().BuildIndex(label, prop);
|
||||
auto dba = db.Access();
|
||||
for (int vi = 0; vi < vertex_count; ++vi) {
|
||||
for (int index = 0; index < index_count; ++index) {
|
||||
|
@ -20,7 +20,7 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
// This makes sure we update the explorer when we bump the snapshot version.
|
||||
// Snapshot layout is described in durability/version.hpp
|
||||
static_assert(durability::kVersion == 10,
|
||||
static_assert(durability::kVersion == 11,
|
||||
"Wrong snapshot version, please update!");
|
||||
|
||||
fs::path snapshot_path(FLAGS_snapshot_file);
|
||||
|
@ -43,7 +43,6 @@ struct DatabaseState {
|
||||
struct IndexKey {
|
||||
std::string label;
|
||||
std::string property;
|
||||
bool is_unique;
|
||||
};
|
||||
|
||||
std::set<Vertex> vertices;
|
||||
@ -70,9 +69,7 @@ bool operator<(const DatabaseState::Edge &first,
|
||||
bool operator<(const DatabaseState::IndexKey &first,
|
||||
const DatabaseState::IndexKey &second) {
|
||||
if (first.label != second.label) return first.label < second.label;
|
||||
if (first.property != second.property)
|
||||
return first.property < second.property;
|
||||
return first.is_unique < second.is_unique;
|
||||
return first.property < second.property;
|
||||
}
|
||||
|
||||
bool operator==(const DatabaseState::Vertex &first,
|
||||
@ -89,8 +86,7 @@ bool operator==(const DatabaseState::Edge &first,
|
||||
|
||||
bool operator==(const DatabaseState::IndexKey &first,
|
||||
const DatabaseState::IndexKey &second) {
|
||||
return first.label == second.label && first.property == second.property &&
|
||||
first.is_unique == second.is_unique;
|
||||
return first.label == second.label && first.property == second.property;
|
||||
}
|
||||
|
||||
bool operator==(const DatabaseState &first, const DatabaseState &second) {
|
||||
@ -196,8 +192,8 @@ class DatabaseEnvironment {
|
||||
// Capture all indices
|
||||
std::set<DatabaseState::IndexKey> indices;
|
||||
for (const auto &key : dba.GetIndicesKeys()) {
|
||||
indices.insert({dba.LabelName(key.label_),
|
||||
dba.PropertyName(key.property_), key.unique_});
|
||||
indices.insert(
|
||||
{dba.LabelName(key.label_), dba.PropertyName(key.property_)});
|
||||
}
|
||||
|
||||
return {vertices, edges, indices};
|
||||
@ -357,12 +353,12 @@ TEST(DumpTest, IndicesKeys) {
|
||||
DatabaseEnvironment db;
|
||||
db.CreateVertex({"Label1", "Label2"}, {{"prop", PropertyValue(10)}}, false);
|
||||
db.Execute("CREATE INDEX ON :Label1(prop);");
|
||||
db.Execute("CREATE UNIQUE INDEX ON :Label2(prop);");
|
||||
db.Execute("CREATE INDEX ON :Label2(prop);");
|
||||
|
||||
auto dba = db.Access();
|
||||
CypherDumpGenerator dump(&dba);
|
||||
EXPECT_EQ(DumpNext(&dump), "CREATE INDEX ON :Label1(prop);");
|
||||
EXPECT_EQ(DumpNext(&dump), "CREATE UNIQUE INDEX ON :Label2(prop);");
|
||||
EXPECT_EQ(DumpNext(&dump), "CREATE INDEX ON :Label2(prop);");
|
||||
EXPECT_EQ(DumpNext(&dump), kCreateInternalIndex);
|
||||
EXPECT_EQ(DumpNext(&dump),
|
||||
"CREATE (:__mg_vertex__:Label1:Label2 {__mg_id__: 0, prop: 10});");
|
||||
@ -403,7 +399,7 @@ TEST(DumpTest, CheckStateSimpleGraph) {
|
||||
db.CreateEdge(w, z, "Knows", {{"how", "school"}});
|
||||
db.CreateEdge(w, z, "Likes", {{"how", "very much"}});
|
||||
// Create few indices
|
||||
db.Execute("CREATE UNIQUE INDEX ON :Person(name);");
|
||||
db.Execute("CREATE INDEX ON :Person(name);");
|
||||
db.Execute("CREATE INDEX ON :Person(unexisting_property);");
|
||||
|
||||
const auto &db_initial_state = db.GetState();
|
||||
|
@ -87,7 +87,7 @@ TEST_F(DistributedDynamicWorker, IndexExistsOnNewWorker) {
|
||||
label = dba->Label("label");
|
||||
property = dba->Property("property");
|
||||
|
||||
dba->BuildIndex(label, property, false);
|
||||
dba->BuildIndex(label, property);
|
||||
EXPECT_TRUE(dba->LabelPropertyIndexExists(label, property));
|
||||
EXPECT_EQ(CountIterable(dba->Vertices(label, property, false)), 100);
|
||||
}
|
||||
@ -159,7 +159,7 @@ TEST_F(DistributedDynamicWorker, IndexExistsOnNewWorkerAfterRecovery) {
|
||||
label = dba->Label("label");
|
||||
property = dba->Property("property");
|
||||
|
||||
dba->BuildIndex(label, property, false);
|
||||
dba->BuildIndex(label, property);
|
||||
EXPECT_TRUE(dba->LabelPropertyIndexExists(label, property));
|
||||
}
|
||||
|
||||
|
@ -144,7 +144,7 @@ TEST_F(DistributedGraphDb, BuildIndexDistributed) {
|
||||
|
||||
{
|
||||
auto dba = master().Access();
|
||||
dba->BuildIndex(label, property, false);
|
||||
dba->BuildIndex(label, property);
|
||||
EXPECT_TRUE(dba->LabelPropertyIndexExists(label, property));
|
||||
EXPECT_EQ(CountIterable(dba->Vertices(label, property, false)), 100);
|
||||
}
|
||||
@ -191,7 +191,7 @@ TEST_F(DistributedGraphDb, BuildIndexConcurrentInsert) {
|
||||
std::this_thread::sleep_for(0.5s);
|
||||
{
|
||||
auto dba = master().Access();
|
||||
dba->BuildIndex(label, property, false);
|
||||
dba->BuildIndex(label, property);
|
||||
EXPECT_TRUE(dba->LabelPropertyIndexExists(label, property));
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@ class DbGenerator {
|
||||
|
||||
void BuildIndex(int seq_number) {
|
||||
dba_.BuildIndex(Label(seq_number % kLabelCount),
|
||||
Property(seq_number % kPropertyCount), false);
|
||||
Property(seq_number % kPropertyCount));
|
||||
}
|
||||
|
||||
EdgeAccessor RandomEdge(bool remove_from_ids = false) {
|
||||
@ -376,7 +376,7 @@ TEST_F(Durability, WalEncoding) {
|
||||
auto e0 = dba.InsertEdge(v0, v1, dba.EdgeType("et0"));
|
||||
ASSERT_EQ(e0.gid(), gid0);
|
||||
e0.PropsSet(dba.Property("p0"), std::vector<PropertyValue>{1, 2, 3});
|
||||
dba.BuildIndex(dba.Label("l1"), dba.Property("p1"), false);
|
||||
dba.BuildIndex(dba.Label("l1"), dba.Property("p1"));
|
||||
dba.DeleteIndex(dba.Label("l1"), dba.Property("p1"));
|
||||
dba.Commit();
|
||||
|
||||
@ -430,7 +430,6 @@ TEST_F(Durability, WalEncoding) {
|
||||
EXPECT_EQ(deltas[8].type, Type::BUILD_INDEX);
|
||||
EXPECT_EQ(deltas[8].label_name, "l1");
|
||||
EXPECT_EQ(deltas[8].property_name, "p1");
|
||||
EXPECT_EQ(deltas[8].unique, false);
|
||||
EXPECT_EQ(deltas[9].type, Type::TRANSACTION_COMMIT);
|
||||
|
||||
// The next two deltas are the DeleteIndex internal transactions.
|
||||
@ -469,7 +468,7 @@ TEST_F(Durability, SnapshotEncoding) {
|
||||
e0.PropsSet(dba.Property("p0"), std::vector<PropertyValue>{1, 2, 3});
|
||||
auto e1 = dba.InsertEdge(v2, v1, dba.EdgeType("et1"));
|
||||
ASSERT_EQ(e1.gid(), gid1);
|
||||
dba.BuildIndex(dba.Label("l1"), dba.Property("p1"), false);
|
||||
dba.BuildIndex(dba.Label("l1"), dba.Property("p1"));
|
||||
dba.Commit();
|
||||
MakeSnapshot(db);
|
||||
}
|
||||
@ -501,10 +500,9 @@ TEST_F(Durability, SnapshotEncoding) {
|
||||
ASSERT_TRUE(dv.IsList());
|
||||
// Label property indices.
|
||||
decoder.ReadValue(&dv);
|
||||
ASSERT_EQ(dv.ValueList().size(), 3);
|
||||
ASSERT_EQ(dv.ValueList().size(), 2);
|
||||
EXPECT_EQ(dv.ValueList()[0].ValueString(), "l1");
|
||||
EXPECT_EQ(dv.ValueList()[1].ValueString(), "p1");
|
||||
EXPECT_EQ(dv.ValueList()[2].ValueBool(), false);
|
||||
|
||||
// Unique constraints
|
||||
decoder.ReadValue(&dv);
|
||||
@ -943,7 +941,7 @@ TEST_F(Durability, UniqueIndexRecoverySnapshotAndWal) {
|
||||
auto label = dba.Label("A");
|
||||
auto property = dba.Property("x");
|
||||
|
||||
dba.BuildIndex(label, property, true);
|
||||
dba.BuildIndex(label, property);
|
||||
|
||||
auto v0 = dba.InsertVertex();
|
||||
v0.add_label(label);
|
||||
@ -987,7 +985,7 @@ TEST_F(Durability, UniqueIndexRecoveryWal) {
|
||||
auto label = dba.Label("A");
|
||||
auto property = dba.Property("x");
|
||||
|
||||
dba.BuildIndex(label, property, true);
|
||||
dba.BuildIndex(label, property);
|
||||
|
||||
auto v0 = dba.InsertVertex();
|
||||
v0.add_label(label);
|
||||
|
@ -19,7 +19,7 @@ TEST(GraphDbTest, GarbageCollectIndices) {
|
||||
};
|
||||
auto label = dba.Label("label");
|
||||
auto property = dba.Property("property");
|
||||
dba.BuildIndex(label, property, false);
|
||||
dba.BuildIndex(label, property);
|
||||
commit();
|
||||
|
||||
auto vertex = dba.InsertVertex();
|
||||
|
@ -104,7 +104,7 @@ TEST_F(GraphDbAccessorIndex, LabelPropertyIndexBuild) {
|
||||
AddVertex(0);
|
||||
|
||||
Commit();
|
||||
dba.BuildIndex(label, property, false);
|
||||
dba.BuildIndex(label, property);
|
||||
Commit();
|
||||
|
||||
EXPECT_EQ(dba.VerticesCount(label, property), 1);
|
||||
@ -112,8 +112,8 @@ TEST_F(GraphDbAccessorIndex, LabelPropertyIndexBuild) {
|
||||
// confirm there is a differentiation of indexes based on (label, property)
|
||||
auto label2 = dba.Label("label2");
|
||||
auto property2 = dba.Property("property2");
|
||||
dba.BuildIndex(label2, property, false);
|
||||
dba.BuildIndex(label, property2, false);
|
||||
dba.BuildIndex(label2, property);
|
||||
dba.BuildIndex(label, property2);
|
||||
Commit();
|
||||
|
||||
EXPECT_EQ(dba.VerticesCount(label, property), 1);
|
||||
@ -122,7 +122,7 @@ TEST_F(GraphDbAccessorIndex, LabelPropertyIndexBuild) {
|
||||
}
|
||||
|
||||
TEST_F(GraphDbAccessorIndex, LabelPropertyIndexDelete) {
|
||||
dba.BuildIndex(label, property, false);
|
||||
dba.BuildIndex(label, property);
|
||||
Commit();
|
||||
EXPECT_TRUE(dba.LabelPropertyIndexExists(label, property));
|
||||
|
||||
@ -133,12 +133,12 @@ TEST_F(GraphDbAccessorIndex, LabelPropertyIndexDelete) {
|
||||
}
|
||||
|
||||
TEST_F(GraphDbAccessorIndex, LabelPropertyIndexBuildTwice) {
|
||||
dba.BuildIndex(label, property, false);
|
||||
EXPECT_THROW(dba.BuildIndex(label, property, false), utils::BasicException);
|
||||
dba.BuildIndex(label, property);
|
||||
EXPECT_THROW(dba.BuildIndex(label, property), utils::BasicException);
|
||||
}
|
||||
|
||||
TEST_F(GraphDbAccessorIndex, LabelPropertyIndexCount) {
|
||||
dba.BuildIndex(label, property, false);
|
||||
dba.BuildIndex(label, property);
|
||||
EXPECT_EQ(dba.VerticesCount(label, property), 0);
|
||||
EXPECT_EQ(Count(dba.Vertices(label, property, true)), 0);
|
||||
for (int i = 0; i < 14; ++i) AddVertex(0);
|
||||
@ -159,7 +159,7 @@ TEST(GraphDbAccessorIndexApi, LabelPropertyBuildIndexConcurrent) {
|
||||
try {
|
||||
// This could either pass or throw.
|
||||
dba.BuildIndex(dba.Label("l" + std::to_string(index)),
|
||||
dba.Property("p" + std::to_string(index)), false);
|
||||
dba.Property("p" + std::to_string(index)));
|
||||
// If it throws, make sure the exception is right.
|
||||
} catch (const database::TransactionException &e) {
|
||||
// Nothing to see here, move along.
|
||||
@ -186,7 +186,7 @@ TEST(GraphDbAccessorIndexApi, LabelPropertyBuildIndexConcurrent) {
|
||||
x, testing::AllOf(testing::Ge(center - 2), testing::Le(center + 2)));
|
||||
|
||||
TEST_F(GraphDbAccessorIndex, LabelPropertyValueCount) {
|
||||
dba.BuildIndex(label, property, false);
|
||||
dba.BuildIndex(label, property);
|
||||
|
||||
// add some vertices without the property
|
||||
for (int i = 0; i < 20; i++) AddVertex();
|
||||
@ -230,7 +230,7 @@ TEST_F(GraphDbAccessorIndex, LabelPropertyValueCount) {
|
||||
#undef EXPECT_WITH_MARGIN
|
||||
|
||||
TEST_F(GraphDbAccessorIndex, LabelPropertyValueIteration) {
|
||||
dba.BuildIndex(label, property, false);
|
||||
dba.BuildIndex(label, property);
|
||||
Commit();
|
||||
|
||||
// insert 10 verties and and check visibility
|
||||
@ -243,7 +243,7 @@ TEST_F(GraphDbAccessorIndex, LabelPropertyValueIteration) {
|
||||
}
|
||||
|
||||
TEST_F(GraphDbAccessorIndex, LabelPropertyValueSorting) {
|
||||
dba.BuildIndex(label, property, false);
|
||||
dba.BuildIndex(label, property);
|
||||
Commit();
|
||||
|
||||
std::vector<PropertyValue> expected_property_value(50, 0);
|
||||
@ -371,7 +371,7 @@ TEST_F(GraphDbAccessorIndex, LabelPropertyValueSorting) {
|
||||
class GraphDbAccessorIndexRange : public GraphDbAccessorIndex {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
dba.BuildIndex(label, property, false);
|
||||
dba.BuildIndex(label, property);
|
||||
for (int i = 0; i < 100; i++) AddVertex(i / 10);
|
||||
|
||||
ASSERT_EQ(Count(dba.Vertices(false)), 0);
|
||||
@ -450,29 +450,3 @@ TEST_F(GraphDbAccessorIndexRange, RangeInterationIncompatibleTypes) {
|
||||
EXPECT_EQ(Count(Vertices(nullopt, Inclusive(1000.0))), 100);
|
||||
EXPECT_EQ(Count(Vertices(Inclusive(0.0), nullopt)), 100);
|
||||
}
|
||||
|
||||
TEST_F(GraphDbAccessorIndex, UniqueConstraintViolationOnInsert) {
|
||||
dba.BuildIndex(label, property, true);
|
||||
Commit();
|
||||
AddVertex(0);
|
||||
EXPECT_THROW(AddVertex(0), database::ConstraintViolationException);
|
||||
}
|
||||
|
||||
TEST_F(GraphDbAccessorIndex, UniqueConstraintViolationOnBuild) {
|
||||
AddVertex(0);
|
||||
AddVertex(0);
|
||||
Commit();
|
||||
EXPECT_THROW(dba.BuildIndex(label, property, true),
|
||||
database::ConstraintViolationException);
|
||||
}
|
||||
|
||||
TEST_F(GraphDbAccessorIndex, UniqueConstraintUpdateProperty) {
|
||||
dba.BuildIndex(label, property, true);
|
||||
AddVertex(0);
|
||||
auto vertex_accessor = dba.InsertVertex();
|
||||
vertex_accessor.add_label(label);
|
||||
vertex_accessor.PropsSet(property, 10);
|
||||
|
||||
EXPECT_THROW(vertex_accessor.PropsSet(property, 0),
|
||||
database::ConstraintViolationException);
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ class QueryCostEstimator : public ::testing::Test {
|
||||
|
||||
void SetUp() {
|
||||
// create the index in the current db accessor and then swap it to a new one
|
||||
dba.BuildIndex(label, property, false);
|
||||
dba.BuildIndex(label, property);
|
||||
dba = db.Access();
|
||||
}
|
||||
|
||||
|
@ -1594,7 +1594,7 @@ TEST(QueryPlan, ScanAllByLabelProperty) {
|
||||
vertex.PropsSet(prop, value);
|
||||
}
|
||||
dba.Commit();
|
||||
db.Access().BuildIndex(label, prop, false);
|
||||
db.Access().BuildIndex(label, prop);
|
||||
}
|
||||
auto dba = db.Access();
|
||||
ASSERT_EQ(14, CountIterable(dba.Vertices(false)));
|
||||
@ -1659,7 +1659,7 @@ TEST(QueryPlan, ScanAllByLabelPropertyEqualityNoError) {
|
||||
string_vertex.add_label(label);
|
||||
string_vertex.PropsSet(prop, "string");
|
||||
dba.Commit();
|
||||
db.Access().BuildIndex(label, prop, false);
|
||||
db.Access().BuildIndex(label, prop);
|
||||
}
|
||||
auto dba = db.Access();
|
||||
EXPECT_EQ(2, CountIterable(dba.Vertices(false)));
|
||||
@ -1696,7 +1696,7 @@ TEST(QueryPlan, ScanAllByLabelPropertyValueError) {
|
||||
}
|
||||
dba.Commit();
|
||||
}
|
||||
db.Access().BuildIndex(label, prop, false);
|
||||
db.Access().BuildIndex(label, prop);
|
||||
auto dba = db.Access();
|
||||
EXPECT_EQ(2, CountIterable(dba.Vertices(false)));
|
||||
// MATCH (m), (n :label {prop: m})
|
||||
@ -1724,7 +1724,7 @@ TEST(QueryPlan, ScanAllByLabelPropertyRangeError) {
|
||||
}
|
||||
dba.Commit();
|
||||
}
|
||||
db.Access().BuildIndex(label, prop, false);
|
||||
db.Access().BuildIndex(label, prop);
|
||||
auto dba = db.Access();
|
||||
EXPECT_EQ(2, CountIterable(dba.Vertices(false)));
|
||||
// MATCH (m), (n :label {prop: m})
|
||||
@ -1775,7 +1775,7 @@ TEST(QueryPlan, ScanAllByLabelPropertyEqualNull) {
|
||||
vertex_with_prop.add_label(label);
|
||||
vertex_with_prop.PropsSet(prop, 42);
|
||||
dba.Commit();
|
||||
db.Access().BuildIndex(label, prop, false);
|
||||
db.Access().BuildIndex(label, prop);
|
||||
}
|
||||
auto dba = db.Access();
|
||||
EXPECT_EQ(2, CountIterable(dba.Vertices(false)));
|
||||
@ -1809,7 +1809,7 @@ TEST(QueryPlan, ScanAllByLabelPropertyRangeNull) {
|
||||
vertex_with_prop.add_label(label);
|
||||
vertex_with_prop.PropsSet(prop, 42);
|
||||
dba.Commit();
|
||||
db.Access().BuildIndex(label, prop, false);
|
||||
db.Access().BuildIndex(label, prop);
|
||||
}
|
||||
auto dba = db.Access();
|
||||
EXPECT_EQ(2, CountIterable(dba.Vertices(false)));
|
||||
@ -1839,7 +1839,7 @@ TEST(QueryPlan, ScanAllByLabelPropertyNoValueInIndexContinuation) {
|
||||
v.add_label(label);
|
||||
v.PropsSet(prop, 2);
|
||||
dba.Commit();
|
||||
db.Access().BuildIndex(label, prop, false);
|
||||
db.Access().BuildIndex(label, prop);
|
||||
}
|
||||
auto dba = db.Access();
|
||||
EXPECT_EQ(1, CountIterable(dba.Vertices(false)));
|
||||
@ -1879,7 +1879,7 @@ TEST(QueryPlan, ScanAllEqualsScanAllByLabelProperty) {
|
||||
dba.Commit();
|
||||
}
|
||||
|
||||
db.Access().BuildIndex(label, prop, false);
|
||||
db.Access().BuildIndex(label, prop);
|
||||
|
||||
// Make sure there are `vertex_count` vertices
|
||||
{
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include "utils/timer.hpp"
|
||||
|
||||
// Snapshot layout is described in durability/version.hpp
|
||||
static_assert(durability::kVersion == 10,
|
||||
static_assert(durability::kVersion == 11,
|
||||
"Wrong snapshot version, please update!");
|
||||
|
||||
bool ValidateNotEmpty(const char *flagname, const std::string &value) {
|
||||
|
Loading…
Reference in New Issue
Block a user