#pragma once
#include <mutex>
#include <shared_mutex>
#include "catalog_entry/catalog_entry.h"
#include "common/case_insensitive_map.h"
namespace lbug {
namespace binder {
struct BoundAlterInfo;
}
namespace storage {
class UndoBuffer;
}
namespace transaction {
class Transaction;
}
using CatalogEntrySet = common::case_insensitive_map_t<catalog::CatalogEntry*>;
namespace catalog {
class LBUG_API CatalogSet {
friend class storage::UndoBuffer;
public:
CatalogSet() = default;
explicit CatalogSet(bool isInternal);
bool containsEntry(const transaction::Transaction* transaction, const std::string& name);
CatalogEntry* getEntry(const transaction::Transaction* transaction, const std::string& name);
common::oid_t createEntry(transaction::Transaction* transaction,
std::unique_ptr<CatalogEntry> entry);
void dropEntry(transaction::Transaction* transaction, const std::string& name,
common::oid_t oid);
void alterTableEntry(transaction::Transaction* transaction,
const binder::BoundAlterInfo& alterInfo);
CatalogEntrySet getEntries(const transaction::Transaction* transaction);
CatalogEntry* getEntryOfOID(const transaction::Transaction* transaction, common::oid_t oid);
void serialize(common::Serializer serializer) const;
void serializeSnapshot(common::Serializer serializer,
const transaction::Transaction* snapshotTxn) const;
static std::unique_ptr<CatalogSet> deserialize(common::Deserializer& deserializer);
common::oid_t getNextOID() {
std::unique_lock lck{mtx};
return nextOID++;
}
common::oid_t getNextOIDNoLock() { return nextOID++; }
private:
bool containsEntryNoLock(const transaction::Transaction* transaction,
const std::string& name) const;
CatalogEntry* getEntryNoLock(const transaction::Transaction* transaction,
const std::string& name) const;
CatalogEntry* createEntryNoLock(const transaction::Transaction* transaction,
std::unique_ptr<CatalogEntry> entry);
CatalogEntry* dropEntryNoLock(const transaction::Transaction* transaction,
const std::string& name, common::oid_t oid);
void validateExistNoLock(const transaction::Transaction* transaction,
const std::string& name) const;
void validateNotExistNoLock(const transaction::Transaction* transaction,
const std::string& name) const;
void emplaceNoLock(std::unique_ptr<CatalogEntry> entry);
void eraseNoLock(const std::string& name);
static std::unique_ptr<CatalogEntry> createDummyEntryNoLock(std::string name,
common::oid_t oid);
static CatalogEntry* traverseVersionChainsForTransactionNoLock(
const transaction::Transaction* transaction, CatalogEntry* currentEntry);
static CatalogEntry* getCommittedEntryNoLock(CatalogEntry* entry);
bool isInternal() const { return nextOID >= INTERNAL_CATALOG_SET_START_OID; }
public:
static constexpr common::oid_t INTERNAL_CATALOG_SET_START_OID = 1LL << 63;
private:
mutable std::shared_mutex mtx;
common::oid_t nextOID = 0;
common::case_insensitive_map_t<std::unique_ptr<CatalogEntry>> entries;
};
} }