#pragma once #include "database/db_transaction.hpp" #include "mvcc/version_list.hpp" #include "storage/indexes/index_record.hpp" #include "storage/model/properties/properties.hpp" #include "storage/model/properties/property.hpp" #include "storage/model/properties/property_family.hpp" #include "transactions/transaction.hpp" template > class RecordAccessor { friend DbAccessor; public: RecordAccessor(vlist_t *vlist, DbTransaction &db) : vlist(vlist), db(db) { assert(vlist != nullptr); } RecordAccessor(T *t, vlist_t *vlist, DbTransaction &db) : record(t), vlist(vlist), db(db) { assert(record != nullptr); assert(vlist != nullptr); } RecordAccessor(RecordAccessor const &other) : record(other.record), vlist(other.vlist), db(other.db) { } RecordAccessor(RecordAccessor &&other) : record(other.record), vlist(other.vlist), db(other.db) { } bool empty() const { return record == nullptr; } // Fills accessor and returns true if there is valid data for current // transaction false otherwise. bool fill() const { const_cast(this)->record = vlist->find(db.trans); return record != nullptr; } const Id &id() const { return vlist->id; } Derived update() const { assert(!empty()); return Derived(vlist->update(db.trans), vlist, db); } bool remove() const { assert(!empty()); return vlist->remove(record, db.trans); } const Property &at(PropertyFamily &key) const { return properties().at(key); } const Property &at(prop_key_t &key) const { return properties().at(key); } template auto at(type_key_t &key) const; template void set(type_key_t &key, Args &&... args) { properties().template set(key, std::forward(args)...); } void set(prop_key_t &key, Property::sptr value) { properties().set(key, std::move(value)); } void clear(prop_key_t &key) { properties().clear(key); } void clear(PropertyFamily &key) { properties().clear(key); } template void accept(Handler &handler) const { properties().template accept(handler); } Properties &properties() const { return record->data.props; } explicit operator bool() const { return record != nullptr; } T const *operator->() const { return record; } T *operator->() { return record; } RecordAccessor &operator=(const RecordAccessor &other) { record = other.record; vlist_t *&vl = const_cast(vlist); vl = other.vlist; return *this; } RecordAccessor &operator=(RecordAccessor &&other) { record = other.record; vlist_t *&vl = const_cast(vlist); vl = other.vlist; return *this; } // Assumes same transaction friend bool operator==(const RecordAccessor &a, const RecordAccessor &b) { return a.vlist == b.vlist; } // Assumes same transaction friend bool operator!=(const RecordAccessor &a, const RecordAccessor &b) { return !(a == b); } protected: IndexRecord create_index_record() { return create_index_record(std::nullptr_t()); } template IndexRecord create_index_record(K &&key) { return IndexRecord(std::move(key), record, vlist); } T *record{nullptr}; vlist_t *const vlist; DbTransaction &db; };