Apply CRTP idiom to database
authorSangwan Kwon <sangwan.kwon@samsung.com>
Sun, 30 Jun 2019 22:24:21 +0000 (07:24 +0900)
committerSangwan Kwon <sangwan.kwon@samsung.com>
Tue, 9 Jul 2019 23:56:30 +0000 (08:56 +0900)
Signed-off-by: Sangwan Kwon <sangwan.kwon@samsung.com>
tsqb/include/crud.hxx
tsqb/include/database.hxx
tsqb/include/table.hxx

index 099719a..fe67524 100644 (file)
@@ -104,6 +104,8 @@ Table& Crud<Table>::selectInternal(ColumnTuple&& ct, bool distinct)
        static_cast<Table*>(this)->cache.clear();
 
        auto columnNames = static_cast<Table*>(this)->getColumnNames(std::move(ct));
+       auto tableNames = static_cast<Table*>(this)->getTableNames(std::move(ct));
+
        std::stringstream ss;
        ss << "SELECT ";
 
@@ -118,7 +120,16 @@ Table& Crud<Table>::selectInternal(ColumnTuple&& ct, bool distinct)
                        ss << ", ";
        }
 
-       ss << " FROM " << static_cast<Table*>(this)->name;
+       ss << " FROM ";
+
+       i = 0;
+       for (const auto& t : tableNames) {
+               ss << t;
+
+               if (i++ < tableNames.size() - 1)
+                       ss << ", ";
+       }
+
        static_cast<Table*>(this)->cache.emplace_back(ss.str());
 
        return *(static_cast<Table*>(this));
index 27c26e9..89a6f03 100644 (file)
 
 #pragma once
 
+#include "crud.hxx"
+#include "condition.hxx"
+#include "expression.hxx"
+#include "table-pack.hxx"
+#include "tuple-helper.hxx"
+#include "util.hxx"
+
 #include <vector>
 #include <set>
 #include <string>
 #include <sstream>
 #include <algorithm>
 
-#include "table-pack.hxx"
-#include "tuple-helper.hxx"
-#include "condition.hxx"
-#include "expression.hxx"
-#include "util.hxx"
-
 namespace tsqb {
 
 template<typename... Tables>
-class Database {
+class Database : public Crud<Database<Tables...>> {
 public:
        using Self = Database<Tables...>;
 
-       // TODO(Sangwan): Use Crud class
-       template<typename... ColumnTypes>
-       Self& select(ColumnTypes&&... cts);
-
-       template<typename Expr>
-       Self& where(Expr expr);
+       // Functions for Crud
+       template<typename Cs>
+       std::set<std::string> getTableNames(Cs&& tuple) const noexcept;
+       template<typename Cs>
+       std::vector<std::string> getColumnNames(Cs&& tuple) const noexcept;
+       template<typename ColumnType>
+       std::string getColumnName(ColumnType&& type) const noexcept;
 
        template<typename Table>
        Self& join(condition::Join type = condition::Join::INNER);
@@ -56,6 +58,7 @@ public:
        operator std::string();
 
        std::string name;
+       std::vector<std::string> cache;
 
 private:
        using TablePackType = internal::TablePack<Tables...>;
@@ -67,12 +70,6 @@ private:
        template<typename ...Ts>
        friend Database<Ts...> make_database(const std::string& name, Ts&& ...tables);
 
-       template<typename Cs>
-       std::set<std::string> getTableNames(Cs&& tuple);
-
-       template<typename Cs>
-       std::vector<std::string> getColumnNames(Cs&& tuple);
-
        struct GetTableNames {
                TablePackType tablePack;
                std::set<std::string> names;
@@ -105,17 +102,7 @@ private:
                }
        };
 
-       template<typename L, typename R>
-       std::string processWhere(condition::And<L,R>& expr);
-
-       template<typename L, typename R>
-       std::string processWhere(condition::Or<L,R>& expr);
-
-       template<typename Expr>
-       std::string processWhere(Expr expr);
-
        TablePackType tablePack;
-       std::vector<std::string> cache;
 };
 
 template<typename ...Tables>
@@ -130,54 +117,6 @@ Database<Tables...>::Database(const std::string& name, TablePackType&& tablePack
        : name(name), tablePack(std::move(tablePack)) {}
 
 template<typename... Tables>
-template<typename... ColumnTypes>
-Database<Tables...>& Database<Tables...>::select(ColumnTypes&&... cts)
-{
-       this->cache.clear();
-
-       auto columnTuple = std::make_tuple(std::forward<ColumnTypes>(cts)...);
-       auto columnNames = this->getColumnNames(std::move(columnTuple));
-       auto tableNames = this->getTableNames(std::move(columnTuple));
-
-       std::stringstream ss;
-       ss << "SELECT ";
-
-       int i = 0;
-       for (const auto& c : columnNames) {
-               ss << c;
-
-               if (i++ < columnNames.size() - 1)
-                       ss << ", ";
-       }
-
-       ss << " FROM ";
-
-       i = 0;
-       for (const auto& t : tableNames) {
-               ss << t;
-
-               if (i++ < tableNames.size() - 1)
-                       ss << ", ";
-       }
-
-       cache.emplace_back(ss.str());
-
-       return *this;
-}
-
-template<typename... Tables>
-template<typename Expr>
-Database<Tables...>& Database<Tables...>::where(Expr expr)
-{
-       std::stringstream ss;
-       ss << "WHERE " << this->processWhere(expr);
-
-       this->cache.emplace_back(ss.str());
-
-       return *this;
-}
-
-template<typename... Tables>
 template<typename Table>
 Database<Tables...>& Database<Tables...>::join(condition::Join type)
 {
@@ -222,7 +161,7 @@ Database<Tables...>::operator std::string()
 
 template<typename... Tables>
 template<typename Cs>
-std::set<std::string> Database<Tables...>::getTableNames(Cs&& tuple)
+std::set<std::string> Database<Tables...>::getTableNames(Cs&& tuple) const noexcept
 {
        GetTableNames closure(this->tablePack);
        tuple_helper::for_each(std::forward<Cs>(tuple), closure);
@@ -232,7 +171,7 @@ std::set<std::string> Database<Tables...>::getTableNames(Cs&& tuple)
 
 template<typename... Tables>
 template<typename Cs>
-std::vector<std::string> Database<Tables...>::getColumnNames(Cs&& tuple)
+std::vector<std::string> Database<Tables...>::getColumnNames(Cs&& tuple) const noexcept
 {
        GetColumnNames closure(this->tablePack);
        tuple_helper::for_each(std::forward<Cs>(tuple), closure);
@@ -241,38 +180,11 @@ std::vector<std::string> Database<Tables...>::getColumnNames(Cs&& tuple)
 }
 
 template<typename... Tables>
-template<typename L, typename R>
-std::string Database<Tables...>::processWhere(condition::And<L,R>& expr)
-{
-       std::stringstream ss;
-       ss << this->processWhere(expr.l) << " ";
-       ss << static_cast<std::string>(expr) << " ";
-       ss << this->processWhere(expr.r);
-
-       return ss.str();
-}
-
-template<typename... Tables>
-template<typename L, typename R>
-std::string Database<Tables...>::processWhere(condition::Or<L,R>& expr)
-{
-       std::stringstream ss;
-       ss << this->processWhere(expr.l) << " ";
-       ss << static_cast<std::string>(expr) << " ";
-       ss << this->processWhere(expr.r);
-
-       return ss.str();
-}
-
-template<typename... Tables>
-template<typename Expr>
-std::string Database<Tables...>::processWhere(Expr expr)
+template<typename ColumnType>
+std::string Database<Tables...>::getColumnName(ColumnType&& type) const noexcept
 {
-       std::stringstream ss;
-       ss << this->tablePack.getColumnName(expr.l);
-       ss << " " << std::string(expr) << " ?";
-
-       return ss.str();
+       auto column = make_column("anonymous", type);
+       return this->tablePack.getColumnName(std::move(column));
 }
 
 } // namespace tsqb
index 439002b..1d6df59 100644 (file)
@@ -40,11 +40,14 @@ public:
        using ColumnPackType = internal::ColumnPack<Columns...>;
        using TableType = typename ColumnPackType::TableType;
 
+       // Functions for Crud
+       template<typename Cs>
+       std::vector<std::string> getColumnNames(Cs&& tuple) const noexcept;
+       template<typename Cs>
+       std::set<std::string> getTableNames(Cs&& tuple) const noexcept;
        template<typename ColumnType>
        std::string getColumnName(ColumnType&& type) const noexcept;
 
-       template<typename Cs>
-       std::vector<std::string> getColumnNames(Cs&& tuple) const noexcept;
        std::vector<std::string> getColumnNames(void) const noexcept;
 
        template<typename That>
@@ -94,6 +97,13 @@ Table<Columns...>::Table(const std::string& name, ColumnPackType&& columnPack)
 
 template<typename... Columns>
 template<typename Cs>
+std::set<std::string> Table<Columns...>::getTableNames(Cs&& tuple) const noexcept
+{
+       return {this->name};
+}
+
+template<typename... Columns>
+template<typename Cs>
 std::vector<std::string> Table<Columns...>::getColumnNames(Cs&& tuple) const noexcept
 {
        GetColumnNames closure(this->columnPack);