c++17: Refactor database with generic lambda
authorSangwan Kwon <sangwan.kwon@samsung.com>
Thu, 30 Jan 2020 04:13:32 +0000 (13:13 +0900)
committerSangwan Kwon <sangwan.kwon@samsung.com>
Thu, 30 Jan 2020 04:54:54 +0000 (13:54 +0900)
Signed-off-by: Sangwan Kwon <sangwan.kwon@samsung.com>
src/vist/query-builder/column-pack.hpp [deleted file]
src/vist/query-builder/database.hpp
src/vist/query-builder/table-pack.hpp [deleted file]
src/vist/query-builder/tests/table.cpp

diff --git a/src/vist/query-builder/column-pack.hpp b/src/vist/query-builder/column-pack.hpp
deleted file mode 100644 (file)
index 7c759f3..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- *  Copyright (c) 2017-present Samsung Electronics Co., Ltd All Rights Reserved
- *
- *  Licensed 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
- */
-
-#pragma once
-
-#include "tuple-helper.hpp"
-#include "type.hpp"
-
-#include <string>
-#include <tuple>
-#include <vector>
-
-namespace vist {
-namespace tsqb {
-namespace internal {
-
-template<typename... Columns>
-class ColumnPack final {
-public:
-       using TableType = typename std::tuple_element<0, std::tuple<Columns...>>::type::TableType;
-       using TupleType = std::tuple<Columns...>;
-
-       explicit ColumnPack(Columns&& ...columns) : columns(columns...)
-       {
-       }
-
-       template<typename Column>
-       std::string getName(const Column& column) const noexcept
-       {
-               std::string name;
-               auto predicate = [&name, &column](const auto& iter) {
-                       if (type::cast_compare(column, iter.type)) 
-                               name = iter.name;
-               };
-
-               tuple_helper::for_each(this->columns, predicate);
-
-               return name;
-       }
-
-       std::vector<std::string> getNames(void) const noexcept
-       {
-               std::vector<std::string> names;
-               auto closure = [&names](const auto& iter) {
-                       names.push_back(iter.name);
-               };
-
-               tuple_helper::for_each(this->columns, closure);
-
-               return names;
-       }
-
-       std::size_t size() const noexcept
-       {
-               return std::tuple_size<TupleType>::value;
-       }
-
-private:
-       std::tuple<Columns...> columns;
-};
-
-} // namespace internal
-} // namespace tsqb
-} // namespace vist
index 9cfa109..b9dee5f 100644 (file)
 
 #pragma once
 
-#include "crud.hpp"
+#include "column.hpp"
 #include "condition.hpp"
+#include "crud.hpp"
 #include "expression.hpp"
-#include "table-pack.hpp"
 #include "tuple-helper.hpp"
 #include "util.hpp"
 
-#include <vector>
+#include <algorithm>
 #include <set>
-#include <string>
 #include <sstream>
-#include <algorithm>
+#include <string>
+#include <tuple>
+#include <vector>
 
 namespace vist {
 namespace tsqb {
@@ -37,15 +38,22 @@ class Database : public Crud<Database<Tables...>> {
 public:
        using Self = Database<Tables...>;
 
-       virtual ~Database() = default;
+       explicit Database(const std::string& name, Tables ...tables) :
+               name(name), tables(tables...) {}
+
+       template<typename Table>
+       Self& join(condition::Join type = condition::Join::INNER);
+
+       template<typename Expr>
+       Self& on(Expr expr);
+
+       std::size_t size() const noexcept;
 
-       Database(const Database&) = delete;
-       Database& operator=(const Database&) = delete;
+       operator std::string();
 
-       Database(Database&&) = default;
-       Database& operator=(Database&&) = default;
+       std::string name;
 
-       // Functions for Crud
+public: // CRTP(Curiously Recurring Template Pattern) for CRUD
        template<typename Cs>
        std::set<std::string> getTableNames(Cs&& tuple) const noexcept;
        template<typename Cs>
@@ -55,73 +63,24 @@ public:
        template<typename ColumnType>
        std::string getColumnName(ColumnType&& type) const noexcept;
 
-       template<typename Table>
-       Self& join(condition::Join type = condition::Join::INNER);
-
-       template<typename Expr>
-       Self& on(Expr expr);
-
-       operator std::string();
-
-       std::string name;
        std::vector<std::string> cache;
 
 private:
-       using TablePackType = internal::TablePack<Tables...>;
        using ColumnNames = std::vector<std::string>;
        using TableNames = std::set<std::string>;
 
-       explicit Database(const std::string& name, TablePackType&& tablePack);
-
        template<typename ...Ts>
        friend Database<Ts...> make_database(const std::string& name, Ts&& ...tables);
 
-       struct GetTableNames {
-               const TablePackType& tablePack;
-               std::set<std::string> names;
-               GetTableNames(const TablePackType& tablePack) : tablePack(tablePack) {}
-
-               template <typename T>
-               void operator()(T&& type)
-               {
-                       auto column = make_column("anonymous", type);
-                       using TableType = typename decltype(column)::Table;
-                       auto name = this->tablePack.getName(TableType());
-                       if (!name.empty())
-                               names.emplace(name);
-               }
-       };
-
-       struct GetColumnNames {
-               const TablePackType& tablePack;
-               std::vector<std::string> names;
-
-               GetColumnNames(const TablePackType& tablePack) : tablePack(tablePack) {}
-
-               template <typename T>
-               void operator()(T&& type)
-               {
-                       auto column = make_column("anonymous", type);
-                       auto name = this->tablePack.getColumnName(std::move(column));
-                       if (!name.empty())
-                               names.emplace_back(name);
-               }
-       };
-
-       TablePackType tablePack;
+       std::tuple<Tables...> tables;
 };
 
 template<typename ...Tables>
 Database<Tables...> make_database(const std::string& name, Tables&& ...tables)
 {
-       auto tablePack = internal::TablePack<Tables...>(std::forward<Tables>(tables)...);
-       return Database<Tables...>(name, std::move(tablePack));
+       return Database<Tables...>(name, std::forward<Tables>(tables)...);
 }
 
-template<typename ...Tables>
-Database<Tables...>::Database(const std::string& name, TablePackType&& tablePack)
-       : name(name), tablePack(std::move(tablePack)) {}
-
 template<typename... Tables>
 template<typename Table>
 Database<Tables...>& Database<Tables...>::join(condition::Join type)
@@ -129,7 +88,7 @@ Database<Tables...>& Database<Tables...>::join(condition::Join type)
        std::stringstream ss;
        ss << condition::to_string(type) << " ";
        ss << "JOIN ";
-       ss << this->tablePack.getName(Table());
+       ss << this->getTableName(Table());
 
        this->cache.emplace_back(ss.str());
        return *this;
@@ -142,12 +101,12 @@ Database<Tables...>& Database<Tables...>::on(Expr expr)
        std::stringstream ss;
        ss << "ON ";
 
-       auto lname = this->tablePack.getColumnName(std::move(expr.l));
+       auto lname = this->getColumnName(std::move(expr.l.type));
        ss << lname << " ";
 
        ss << std::string(expr) << " ";
 
-       auto rname = this->tablePack.getColumnName(std::move(expr.r));
+       auto rname = this->getColumnName(std::move(expr.r.type));
        ss << rname;
 
        this->cache.emplace_back(ss.str());
@@ -169,35 +128,78 @@ template<typename... Tables>
 template<typename Cs>
 std::set<std::string> Database<Tables...>::getTableNames(Cs&& tuple) const noexcept
 {
-       GetTableNames closure(this->tablePack);
+       std::set<std::string> names;
+
+       auto closure = [this, &names](const auto& type) {
+               auto column = make_column("anonymous", type);
+               using TableType = typename decltype(column)::Table;
+               auto name = this->getTableName(TableType());
+               if (!name.empty())
+                               names.emplace(name);
+       };
+
        tuple_helper::for_each(std::forward<Cs>(tuple), closure);
 
-       return closure.names;
+       return names;
 }
 
 template<typename... Tables>
 template<typename Cs>
 std::vector<std::string> Database<Tables...>::getColumnNames(Cs&& tuple) const noexcept
 {
-       GetColumnNames closure(this->tablePack);
+       std::vector<std::string> names;
+       auto closure = [this, &names](const auto& iter) {
+               auto name = this->getColumnName(iter);
+               if (!name.empty())
+                       names.emplace_back(name);
+       };
+
        tuple_helper::for_each(std::forward<Cs>(tuple), closure);
 
-       return closure.names;
+       return names;
 }
 
 template<typename... Tables>
-template<typename TableType>
-std::string Database<Tables...>::getTableName(TableType&& type) const noexcept
+template<typename Table>
+std::string Database<Tables...>::getTableName(Table&& table) const noexcept
 {
-       return this->tablePack.getName(std::forward<TableType>(type));
+       std::string name;
+       auto predicate = [&name, &table](const auto& iter) {
+               if (iter.compare(table))
+                       name = iter.name;
+       };
+
+       tuple_helper::for_each(this->tables, predicate);
+
+       return name;
 }
 
 template<typename... Tables>
 template<typename ColumnType>
-std::string Database<Tables...>::getColumnName(ColumnType&& type) const noexcept
+std::string Database<Tables...>::getColumnName(ColumnType&& column) const noexcept
+{
+       Column anonymous("anonymous", column);
+       using TableType = typename decltype(anonymous)::Table;
+       TableType table;
+
+       std::string name;
+       auto predicate = [&name, &table, &column](const auto& iter) {
+               if (iter.compare(table)) {
+                       auto cname = iter.getColumnName(column);
+                       name = iter.name + "." + cname;
+               }
+       };
+
+       tuple_helper::for_each(this->tables, predicate);
+
+       return name;
+}
+
+template<typename... Tables>
+std::size_t Database<Tables...>::size() const noexcept
 {
-       auto column = make_column("anonymous", type);
-       return this->tablePack.getColumnName(std::move(column));
+       using TupleType = std::tuple<Tables...>;
+       return std::tuple_size<TupleType>::value;
 }
 
 } // namespace tsqb
diff --git a/src/vist/query-builder/table-pack.hpp b/src/vist/query-builder/table-pack.hpp
deleted file mode 100644 (file)
index d76b309..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- *  Copyright (c) 2017-present Samsung Electronics Co., Ltd All Rights Reserved
- *
- *  Licensed 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
- */
-
-#pragma once
-
-#include "tuple-helper.hpp"
-
-#include <set>
-#include <string>
-#include <tuple>
-#include <vector>
-
-namespace vist {
-namespace tsqb {
-namespace internal {
-
-template<typename... Tables>
-class TablePack final {
-public:
-       using TupleType = std::tuple<Tables...>;
-
-       explicit TablePack(Tables ...tables) : tables(tables...)
-       {
-       }
-
-       template<typename TableType>
-       std::string getName(TableType&& table) const noexcept
-       {
-               std::string name;
-               auto predicate = [&name, &table](const auto& iter) {
-                       if (iter.compare(table))
-                               name = iter.name;
-               };
-
-               tuple_helper::for_each(this->tables, predicate);
-
-               return name;
-       }
-
-       template<typename ColumnType>
-       std::string getColumnName(ColumnType&& column) const noexcept
-       {
-               using TableType = typename ColumnType::Table;
-
-               std::string name;
-               TableType table;
-               auto predicate = [&name, &table, column](const auto& iter) {
-                       if (iter.compare(table)) {
-                               auto cname = iter.getColumnName(column.type);
-                               name = iter.name + "." + cname;
-                       }
-               };
-
-               tuple_helper::for_each(this->tables, predicate);
-
-               return name;
-       }
-
-private:
-       std::tuple<Tables...> tables;
-};
-
-} // namespace internal
-} // namespace tsqb
-} // namespace vist
index dda8ca9..038482a 100644 (file)
 #include <gtest/gtest.h>
 
 #include <vist/query-builder/column.hpp>
-#include <vist/query-builder/table-pack.hpp>
 #include <vist/query-builder/table.hpp>
 
 using namespace vist::tsqb;
-using namespace vist::tsqb::internal;
 
 namespace {
 
@@ -49,8 +47,6 @@ Table table2 { "table2", Column("column1", &Table2::column1),
                                                 Column("column4", &Table2::column4),
                                                 Column("column5", &Table2::column5) };
 
-TablePack tables { table1, table2 };
-
 } // anonymous namespace
 
 TEST(TableTests, size)
@@ -85,10 +81,3 @@ TEST(TableTests, compare)
 {
        EXPECT_TRUE(table1.compare(Table1()));
 }
-
-TEST(TableTests, pack_get_column)
-{
-       EXPECT_EQ(tables.getColumnName(Column("anonymous", &Table1::column1)), "table1.column1");
-       EXPECT_EQ(tables.getColumnName(Column("anonymous", &Table1::column2)), "table1.column2");
-       EXPECT_EQ(tables.getColumnName(Column("anonymous", &Table1::column3)), "table1.column3");
-}