#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