Add storage side capabilites to retrieve metadata
In order to get the required metadata in constant time we need to keep track of the node labels and edge types that were ever present in the database. This is done by the two axuiliary datastructures that are present in the storage instances. The ability to get this metadata is propagated to the DBAccessor class, which the query modules can interact with.
This commit is contained in:
parent
16b8c7b27c
commit
50c485fe40
@ -597,6 +597,13 @@ class DbAccessor final {
|
||||
return accessor_->ApproximateVertexCount(label, property, lower, upper);
|
||||
}
|
||||
|
||||
std::vector<std::string> ListAllPossiblyPresentVertexLabels() const {
|
||||
return accessor_->ListAllPossiblyPresentVertexLabels();
|
||||
}
|
||||
std::vector<std::string> ListAllPossiblyPresentEdgeTypes() const {
|
||||
return accessor_->ListAllPossiblyPresentEdgeTypes();
|
||||
}
|
||||
|
||||
storage::IndicesInfo ListAllIndices() const { return accessor_->ListAllIndices(); }
|
||||
|
||||
storage::ConstraintsInfo ListAllConstraints() const { return accessor_->ListAllConstraints(); }
|
||||
|
@ -944,6 +944,7 @@ Result<EdgeAccessor> DiskStorage::DiskAccessor::CreateEdge(VertexAccessor *from,
|
||||
transaction_.manyDeltasCache.Invalidate(from_vertex, edge_type, EdgeDirection::OUT);
|
||||
transaction_.manyDeltasCache.Invalidate(to_vertex, edge_type, EdgeDirection::IN);
|
||||
|
||||
storage_->stored_edge_types_.insert(edge_type);
|
||||
storage_->edge_count_.fetch_add(1, std::memory_order_acq_rel);
|
||||
|
||||
return EdgeAccessor(edge, edge_type, from_vertex, to_vertex, storage_, &transaction_);
|
||||
|
@ -331,6 +331,7 @@ Result<EdgeAccessor> InMemoryStorage::InMemoryAccessor::CreateEdge(VertexAccesso
|
||||
if (to_vertex->deleted) return Error::DELETED_OBJECT;
|
||||
}
|
||||
|
||||
storage_->stored_edge_types_.insert(edge_type);
|
||||
auto *mem_storage = static_cast<InMemoryStorage *>(storage_);
|
||||
auto gid = storage::Gid::FromUint(mem_storage->edge_id_.fetch_add(1, std::memory_order_acq_rel));
|
||||
EdgeRef edge(gid);
|
||||
@ -395,6 +396,8 @@ Result<EdgeAccessor> InMemoryStorage::InMemoryAccessor::CreateEdgeEx(VertexAcces
|
||||
if (to_vertex->deleted) return Error::DELETED_OBJECT;
|
||||
}
|
||||
|
||||
storage_->stored_edge_types_.insert(edge_type);
|
||||
|
||||
// NOTE: When we update the next `edge_id_` here we perform a RMW
|
||||
// (read-modify-write) operation that ISN'T atomic! But, that isn't an issue
|
||||
// because this function is only called from the replication delta applier
|
||||
|
@ -122,6 +122,24 @@ std::optional<uint64_t> Storage::Accessor::GetTransactionId() const {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<std::string> Storage::Accessor::ListAllPossiblyPresentVertexLabels() const {
|
||||
std::vector<std::string> vertex_labels;
|
||||
vertex_labels.reserve(storage_->stored_node_labels_.size());
|
||||
for (const auto label : storage_->stored_node_labels_) {
|
||||
vertex_labels.emplace_back(LabelToName(label));
|
||||
}
|
||||
return vertex_labels;
|
||||
}
|
||||
|
||||
std::vector<std::string> Storage::Accessor::ListAllPossiblyPresentEdgeTypes() const {
|
||||
std::vector<std::string> edge_types;
|
||||
edge_types.reserve(storage_->stored_edge_types_.size());
|
||||
for (const auto edge_type : storage_->stored_edge_types_) {
|
||||
edge_types.emplace_back(EdgeTypeToName(edge_type));
|
||||
}
|
||||
return edge_types;
|
||||
}
|
||||
|
||||
void Storage::Accessor::AdvanceCommand() {
|
||||
transaction_.manyDeltasCache.Clear(); // TODO: Just invalidate the View::OLD cache, NEW should still be fine
|
||||
++transaction_.command_id;
|
||||
|
@ -237,6 +237,10 @@ class Storage {
|
||||
|
||||
const std::string &id() const { return storage_->id(); }
|
||||
|
||||
std::vector<std::string> ListAllPossiblyPresentVertexLabels() const;
|
||||
|
||||
std::vector<std::string> ListAllPossiblyPresentEdgeTypes() const;
|
||||
|
||||
virtual utils::BasicResult<StorageIndexDefinitionError, void> CreateIndex(LabelId label) = 0;
|
||||
|
||||
virtual utils::BasicResult<StorageIndexDefinitionError, void> CreateIndex(LabelId label, PropertyId property) = 0;
|
||||
@ -384,6 +388,18 @@ class Storage {
|
||||
Indices indices_;
|
||||
Constraints constraints_;
|
||||
|
||||
// Datastructures to provide fast retrieval of node-label and
|
||||
// edge-type related metadata.
|
||||
// Currently we should not remove any node-labels or edge-types even
|
||||
// if the set of given types are currently not present in the
|
||||
// database. This metadata is usually used by client side
|
||||
// applications that want to be aware of the kind of data that *may*
|
||||
// be present in the database.
|
||||
|
||||
// TODO(gvolfing): check if this would be faster with flat_maps.
|
||||
std::unordered_set<LabelId> stored_node_labels_;
|
||||
std::unordered_set<EdgeTypeId> stored_edge_types_;
|
||||
|
||||
std::atomic<uint64_t> vertex_id_{0};
|
||||
std::atomic<uint64_t> edge_id_{0};
|
||||
const std::string id_; //!< High-level assigned ID
|
||||
|
@ -109,6 +109,7 @@ Result<bool> VertexAccessor::AddLabel(LabelId label) {
|
||||
|
||||
CreateAndLinkDelta(transaction_, vertex_, Delta::RemoveLabelTag(), label);
|
||||
vertex_->labels.push_back(label);
|
||||
storage_->stored_node_labels_.insert(label);
|
||||
|
||||
/// TODO: some by pointers, some by reference => not good, make it better
|
||||
storage_->constraints_.unique_constraints_->UpdateOnAddLabel(label, *vertex_, transaction_->start_timestamp);
|
||||
|
Loading…
Reference in New Issue
Block a user