#pragma once
#include
#include
#include
#include
#include
#include "cexpr/string.hpp"
#include "sql/column.hpp"
#include "sql/index.hpp"
#include "sql/row.hpp"
namespace sql
{
template <:string name typename index typename... cols>
class schema
{
public:
static constexpr auto name{ Name };
using row_type = sql::variadic_row::row_type;
using container = typename
std::conditional_t<
std::is_same_v>,
std::vector,
std::multiset>
>;
using const_iterator = typename container::const_iterator;
schema() = default;
template
schema(std::vector const& col, Types const&... cols) : schema{}
{
insert(col, cols...);
}
template
schema(std::vector&& col, Types&&... cols) : schema{}
{
insert(std::forward(col), std::forward(cols)...);
}
template
inline void emplace(Types const&... vals)
{
if constexpr (std::is_same_v>)
{
table_.emplace_back(vals...);
}
else
{
table_.emplace(vals...);
}
}
template
inline void emplace(Types&&... vals)
{
if constexpr (std::is_same_v>)
{
table_.emplace_back(vals...);
}
else
{
table_.emplace(vals...);
}
}
template
void insert(std::vector const& col, Types const&... cols)
{
for (std::size_t i{}; i < col.size(); ++i)
{
emplace(col[i], cols[i]...);
}
}
template
void insert(std::vector&& col, Types&&... cols)
{
for (std::size_t i{}; i < col.size(); ++i)
{
emplace(std::forward(col[i]), std::forward(cols[i])...);
}
}
void insert(row_type const& row)
{
if constexpr (std::is_same_v>)
{
table_.push_back(row);
}
else
{
table_.insert(row);
}
}
void insert(row_type&& row)
{
if constexpr (std::is_same_v>)
{
table_.push_back(std::forward(row));
}
else
{
table_.insert(std::forward(row));
}
}
inline const_iterator begin() const noexcept
{
return table_.begin();
}
inline const_iterator end() const noexcept
{
return table_.end();
}
private:
container table_;
};
namespace
{
template
void fill(std::fstream& fstr, Row& row, [[maybe_unused]] char delim)
{
if constexpr (!std::is_same_v)
{
if constexpr (std::is_same_v)
{
if constexpr (std::is_same_v)
{
std::getline(fstr, row.head());
}
else
{
std::getline(fstr, row.head(), delim);
}
}
else
{
fstr >> row.head();
}
fill(fstr, row.tail(), delim);
}
}
template
void fill(std::fstream& fstr, Row const& row, char delim)
{
if constexpr (!std::is_same_v)
{
fstr << row.head();
if constexpr (std::is_same_v)
{
fstr << '\n';
}
else
{
fstr << delim;
}
fill(fstr, row.tail(), delim);
}
}
} // namespace
// helper function for users to load a data into a schema from a file
template
Schema load(std::string const& file, char delim)
{
auto fstr{ std::fstream(file, fstr.in) };
Schema table{};
typename Schema::row_type row{};
while (fstr)
{
fill(fstr, row, delim);
table.insert(std::move(row));
// in case last stream extraction did not remove newline
if (fstr.get() != '\n')
{
fstr.unget();
}
}
return table;
}
// for compat with previous versions
template
inline Schema load(std::string const& file)
{
return load(file, Delim);
}
// will work with schema and query objects
template
void store(Type const& data, std::string const& file, char delim)
{
auto fstr{ std::fstream(file, fstr.out) };
for (auto const& row : data)
{
fill(fstr, row, delim);
}
}
// for devs who want to use the previous format
template
inline void store(Type const& data, std::string const& file)
{
store(data, file, Delim);
}
} // namespace sql