blob: daaec8cbab7e586567eee587307bb867d10a01fb [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
**/
#ifndef QUICKSTEP_CATALOG_CATALOG_HPP_
#define QUICKSTEP_CATALOG_CATALOG_HPP_
#include <exception>
#include <string>
#include <unordered_map>
#include "catalog/Catalog.pb.h"
#include "catalog/CatalogDatabase.hpp"
#include "catalog/CatalogTypedefs.hpp"
#include "utility/Macros.hpp"
#include "utility/PtrVector.hpp"
namespace quickstep {
/** \addtogroup Catalog
* @{
*/
/**
* @brief Exception thrown for a database name collision.
**/
class DatabaseNameCollision : public std::exception {
public:
/**
* @brief Constructor.
*
* @param db_name The name of the database for which there was a collision.
**/
explicit DatabaseNameCollision(const std::string &db_name)
: message_("DatabaseNameCollision: catalog already has a database ") {
message_.append(db_name);
}
~DatabaseNameCollision() throw() {
}
virtual const char* what() const throw() {
return message_.c_str();
}
private:
std::string message_;
};
/**
* @brief Exception thrown when a database with the specified name can't be
* found.
**/
class DatabaseNameNotFound : public std::exception {
public:
/**
* @brief Constructor.
*
* @param dbName The database name which could not be found.
**/
explicit DatabaseNameNotFound(const std::string &db_name)
: message_("DatabaseNameNotFound: catalog has no database named ") {
message_.append(db_name);
}
~DatabaseNameNotFound() throw() {
}
virtual const char* what() const throw() {
return message_.c_str();
}
private:
std::string message_;
};
/**
* @brief Exception thrown when a database with the specified ID can't be
* found.
**/
class DatabaseIdNotFound : public std::exception {
public:
/**
* @brief Constructor.
*
* @param id The id which could not be found.
**/
explicit DatabaseIdNotFound(const database_id id)
: message_("DatabaseIdNotFound: catalog has no database with ID ") {
message_.append(std::to_string(id));
}
~DatabaseIdNotFound() throw() {
}
virtual const char* what() const throw() {
return message_.c_str();
}
private:
std::string message_;
};
/**
* @brief The entire database catalog.
**/
class Catalog {
public:
typedef std::unordered_map<std::string, CatalogDatabase*>::size_type size_type;
typedef PtrVector<CatalogDatabase, true>::const_skip_iterator const_iterator;
/**
* @brief Construct an empty catalog.
**/
Catalog() {
}
/**
* @brief Reconstruct a catalog from its serialized Protocol Buffer form.
*
* @param proto The Protocol Buffer serialization of a catalog,
* previously produced by getProto().
**/
explicit Catalog(const serialization::Catalog &proto);
/**
* @brief Destructor which recursively destroys children.
**/
~Catalog() {
}
/**
* @brief Check whether a database with the given name exists.
*
* @param db_name The name to check for.
* @return Whether the database exists.
**/
bool hasDatabaseWithName(const std::string &db_name) const {
return (db_map_.find(db_name) != db_map_.end());
}
/**
* @brief Check whether a database with the given id exists.
*
* @param id The id to check for.
* @return Whether the database exists.
**/
bool hasDatabaseWithId(const database_id id) const {
return (idInRange(id) && !db_vec_.elementIsNull(id));
}
/**
* @brief Get a database by name.
*
* @param db_name The name to search for.
* @exception DatabaseNameNotFound No database with the given name exists.
* @return The database with the given name.
**/
const CatalogDatabase& getDatabaseByName(const std::string &db_name) const;
/**
* @brief Get a mutable pointer to a database by name.
*
* @param db_name The name to search for.
* @exception DatabaseNameNotFound No database with the given name exists.
* @return The database with the given name.
**/
CatalogDatabase* getDatabaseByNameMutable(const std::string &db_name);
/**
* @brief Get a database by ID.
*
* @param id The id to search for.
* @exception DatabaseIdNotFound No database with the given ID exists.
* @return The database with the given ID.
**/
const CatalogDatabase& getDatabaseById(const database_id id) const {
if (hasDatabaseWithId(id)) {
return db_vec_[id];
} else {
throw DatabaseIdNotFound(id);
}
}
/**
* @brief Get a mutable pointer to a database by ID.
*
* @param id The id to search for.
* @exception DatabaseIdNotFound No database with the given ID exists.
* @return The database with the given ID.
**/
CatalogDatabase* getDatabaseByIdMutable(const database_id id) {
if (hasDatabaseWithId(id)) {
return &(db_vec_[id]);
} else {
throw DatabaseIdNotFound(id);
}
}
/**
* @brief Add a new database to the catalog. If the database already has an
* ID and/or parent, it will be overwritten.
*
* @param new_db The database to be added.
* @exception DatabaseNameCollision A database with the same name as new_db
* is already present in the catalog.
* @return The id assigned to the database.
**/
database_id addDatabase(CatalogDatabase *new_db);
/**
* @brief Serialize the catalog as Protocol Buffer.
*
* @return The Protocol Buffer representation of the catalog.
**/
serialization::Catalog getProto() const;
/**
* @brief Get the number of child databases.
*
* @return The number of child databases.
**/
size_type size() const {
return db_map_.size();
}
/**
* @brief Get an iterator at the beginning of the child databases.
*
* @return An iterator on the first child database.
**/
const_iterator begin() const {
return db_vec_.begin_skip();
}
/**
* @brief Get an iterator at one-past-the-end of the child databases.
*
* @return An iterator one-past-the-end of the child databases.
**/
const_iterator end() const {
return db_vec_.end_skip();
}
private:
/**
* @brief Check whether a database_id is within the range of IDs contained
* in this Catalog.
*
* @param id The id to check.
* @return true if id is in range, false otherwise.
**/
bool idInRange(const database_id id) const {
return ((id >= 0)
&& (static_cast<PtrVector<CatalogDatabase>::size_type>(id) < db_vec_.size()));
}
/**
* @brief Check whether a serialization::Catalog is fully-formed and
* all parts are valid.
*
* @param proto A serialized Protocol Buffer representation of a Catalog,
* originally generated by getProto().
* @return Whether proto is fully-formed and valid.
**/
static bool ProtoIsValid(const serialization::Catalog &proto);
// A vector of databases, and NULL if it has dropped from the catalog.
PtrVector<CatalogDatabase, true> db_vec_;
// A map from a database name to a pointer to the database.
std::unordered_map<std::string, CatalogDatabase*> db_map_;
DISALLOW_COPY_AND_ASSIGN(Catalog);
};
/** @} */
} // namespace quickstep
#endif // QUICKSTEP_CATALOG_CATALOG_HPP_