Refactor CRTP functions
authorSangwan Kwon <sangwan.kwon@samsung.com>
Thu, 30 Jan 2020 05:23:23 +0000 (14:23 +0900)
committerSangwan Kwon <sangwan.kwon@samsung.com>
Thu, 30 Jan 2020 05:23:23 +0000 (14:23 +0900)
Signed-off-by: Sangwan Kwon <sangwan.kwon@samsung.com>
src/vist/query-builder/crud.hpp
src/vist/query-builder/database.hpp
src/vist/query-builder/table.hpp
src/vist/query-builder/tests/database.cpp [new file with mode: 0644]

index ded5080..a53f64d 100644 (file)
@@ -52,8 +52,8 @@ public:
        T& where(Expr expr);
 
 private:
-       template<typename ColumnTuple>
-       T& selectInternal(ColumnTuple&& ct, bool distinct = false);
+       template<typename... ColumnTypes>
+       T& selectInternal(bool distinct, ColumnTypes&& ...cts);
 
        template<typename L, typename R>
        std::string processWhere(condition::And<L,R>& expr);
@@ -69,16 +69,14 @@ template<typename T>
 template<typename... ColumnTypes>
 T& Crud<T>::select(ColumnTypes&&... cts)
 {
-       auto columnTuple = std::make_tuple(std::forward<ColumnTypes>(cts)...);
-
-       return this->selectInternal(std::move(columnTuple));
+       return this->selectInternal(false, std::forward<ColumnTypes>(cts)...);
 }
 
 template<typename T>
 template<typename Type>
 T& Crud<T>::select(Distinct<Type> distinct)
 {
-       return this->selectInternal(std::move(distinct.value), true);
+       return this->selectInternal(true, std::move(distinct.value));
 }
 
 template<typename T>
@@ -110,13 +108,15 @@ T& Crud<T>::selectAll(void)
 }
 
 template<typename T>
-template<typename ColumnTuple>
-T& Crud<T>::selectInternal(ColumnTuple&& ct, bool distinct)
+template<typename... ColumnTypes>
+T& Crud<T>::selectInternal(bool distinct, ColumnTypes&& ...cts)
 {
        static_cast<T*>(this)->cache.clear();
 
-       auto columnNames = static_cast<T*>(this)->getColumnNames(std::move(ct));
-       auto tableNames = static_cast<T*>(this)->getTableNames(std::move(ct));
+       auto columnNames = static_cast<T*>(this)->getColumnNames(std::forward<ColumnTypes>(cts)...);
+
+       auto tuple = std::tuple(cts...);
+       auto tableNames = static_cast<T*>(this)->getTableNames(std::move(tuple));
 
        std::stringstream ss;
        ss << "SELECT ";
@@ -153,8 +153,7 @@ T& Crud<T>::update(ColumnTypes&&... cts)
 {
        static_cast<T*>(this)->cache.clear();
 
-       auto columnTuple = std::make_tuple(std::forward<ColumnTypes>(cts)...);
-       auto columnNames = static_cast<T*>(this)->getColumnNames(std::move(columnTuple));
+       auto columnNames = static_cast<T*>(this)->getColumnNames(std::forward<ColumnTypes>(cts)...);
 
        std::stringstream ss;
        ss << "UPDATE " << static_cast<T*>(this)->name << " ";
@@ -179,8 +178,7 @@ T& Crud<T>::insert(ColumnTypes&&... cts)
 {
        static_cast<T*>(this)->cache.clear();
 
-       auto columnTuple = std::make_tuple(std::forward<ColumnTypes>(cts)...);
-       auto columnNames = static_cast<T*>(this)->getColumnNames(std::move(columnTuple));
+       auto columnNames = static_cast<T*>(this)->getColumnNames(std::forward<ColumnTypes>(cts)...);
 
        std::stringstream ss;
        ss << "INSERT INTO " << static_cast<T*>(this)->name << " (";
@@ -213,8 +211,7 @@ T& Crud<T>::remove(ColumnTypes&&... cts)
 {
        static_cast<T*>(this)->cache.clear();
 
-       auto columnTuple = std::make_tuple(std::forward<ColumnTypes>(cts)...);
-       auto columnNames = static_cast<T*>(this)->getColumnNames(std::move(columnTuple));
+       auto columnNames = static_cast<T*>(this)->getColumnNames(std::forward<ColumnTypes>(cts)...);
 
        std::stringstream ss;
        ss << "DELETE FROM " << static_cast<T*>(this)->name;
index b9dee5f..a614130 100644 (file)
@@ -54,10 +54,10 @@ public:
        std::string name;
 
 public: // CRTP(Curiously Recurring Template Pattern) 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... Cs>
+       std::vector<std::string> getTableNames(Cs&& ...columns) const noexcept;
+       template<typename... Cs> 
+       std::vector<std::string> getColumnNames(Cs&& ...columns) const noexcept;
        template<typename TableType>
        std::string getTableName(TableType&& type) const noexcept;
        template<typename ColumnType>
@@ -66,9 +66,6 @@ public: // CRTP(Curiously Recurring Template Pattern) for CRUD
        std::vector<std::string> cache;
 
 private:
-       using ColumnNames = std::vector<std::string>;
-       using TableNames = std::set<std::string>;
-
        template<typename ...Ts>
        friend Database<Ts...> make_database(const std::string& name, Ts&& ...tables);
 
@@ -125,8 +122,8 @@ Database<Tables...>::operator std::string()
 }
 
 template<typename... Tables>
-template<typename Cs>
-std::set<std::string> Database<Tables...>::getTableNames(Cs&& tuple) const noexcept
+template<typename... Cs>
+std::vector<std::string> Database<Tables...>::getTableNames(Cs&& ...columns) const noexcept
 {
        std::set<std::string> names;
 
@@ -138,14 +135,15 @@ std::set<std::string> Database<Tables...>::getTableNames(Cs&& tuple) const noexc
                                names.emplace(name);
        };
 
-       tuple_helper::for_each(std::forward<Cs>(tuple), closure);
+       auto tuple = std::tuple(columns...);
+       tuple_helper::for_each(tuple, closure);
 
-       return names;
+       return std::vector<std::string>(names.begin(), names.end());
 }
 
 template<typename... Tables>
-template<typename Cs>
-std::vector<std::string> Database<Tables...>::getColumnNames(Cs&& tuple) const noexcept
+template<typename... Cs>
+std::vector<std::string> Database<Tables...>::getColumnNames(Cs&& ...columns) const noexcept
 {
        std::vector<std::string> names;
        auto closure = [this, &names](const auto& iter) {
@@ -154,7 +152,8 @@ std::vector<std::string> Database<Tables...>::getColumnNames(Cs&& tuple) const n
                        names.emplace_back(name);
        };
 
-       tuple_helper::for_each(std::forward<Cs>(tuple), closure);
+       auto tuple = std::tuple(columns...);
+       tuple_helper::for_each(tuple, closure);
 
        return names;
 }
index 3ec559d..ed2e27f 100644 (file)
@@ -52,12 +52,12 @@ public:
        const std::string name;
 
 public: // CRTP(Curiously Recurring Template Pattern) for CRUD
-       template<typename Cs>
-       std::set<std::string> getTableNames(Cs&& tuple) const noexcept;
+       template<typename... Cs>
+       std::vector<std::string> getTableNames(Cs&& ...coulmns) const noexcept;
        template<typename That>
        std::string getTableName(That&& type) const noexcept;
-       template<typename Cs>
-       std::vector<std::string> getColumnNames(Cs&& tuple) const noexcept;
+       template<typename... Cs>
+       std::vector<std::string> getColumnNames(Cs&& ...columns) const noexcept;
        template<typename Column>
        std::string getColumnName(const Column& column) const noexcept;
 
@@ -83,15 +83,15 @@ std::string Table<Columns...>::getName() const noexcept
 }
 
 template<typename... Columns>
-template<typename Cs>
-std::set<std::string> Table<Columns...>::getTableNames(Cs&&) const noexcept
+template<typename... Cs>
+std::vector<std::string> Table<Columns...>::getTableNames(Cs&& ...) const noexcept
 {
        return {this->name};
 }
 
 template<typename... Columns>
-template<typename Cs>
-std::vector<std::string> Table<Columns...>::getColumnNames(Cs&& tuple) const noexcept
+template<typename... Cs>
+std::vector<std::string> Table<Columns...>::getColumnNames(Cs&& ...columns) const noexcept
 {
        std::vector<std::string> names;
        auto closure = [this, &names](auto type) {
@@ -100,7 +100,8 @@ std::vector<std::string> Table<Columns...>::getColumnNames(Cs&& tuple) const noe
                        names.emplace_back(name);
        };
 
-       tuple_helper::for_each(std::forward<Cs>(tuple), closure);
+       auto tuple = std::tuple(columns...);
+       tuple_helper::for_each(tuple, closure);
 
        return names;
 }
diff --git a/src/vist/query-builder/tests/database.cpp b/src/vist/query-builder/tests/database.cpp
new file mode 100644 (file)
index 0000000..5e23ddb
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ *  Copyright (c) 2020-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
+ */
+
+#include <gtest/gtest.h>
+
+#include <vist/query-builder/column.hpp>
+#include <vist/query-builder/database.hpp>
+#include <vist/query-builder/table.hpp>
+
+using namespace vist::tsqb;
+
+namespace {
+
+struct Table1 {
+       int column1;
+       std::string column2;
+       bool column3;
+};
+
+struct Table2 {
+       int column1;
+       std::string column2;
+       bool column3;
+       float column4;
+       double column5;
+};
+
+Table table1 { "table1", Column("column1", &Table1::column1),
+                                                Column("column2", &Table1::column2),
+                                                Column("column3", &Table1::column3) };
+
+Table table2 { "table2", Column("column1", &Table2::column1),
+                                                Column("column2", &Table2::column2),
+                                                Column("column3", &Table2::column3),
+                                                Column("column4", &Table2::column4),
+                                                Column("column5", &Table2::column5) };
+
+Database database { "database", table1, table2 };
+
+} // anonymous namespace
+
+TEST(DatabaseTests, size)
+{
+       EXPECT_EQ(database.size(), 2);
+}
+
+TEST(DatabaseTests, get_name)
+{
+       EXPECT_EQ(database.name, "database");
+
+       EXPECT_EQ(database.getTableName(Table1()), "table1");
+       EXPECT_EQ(database.getTableName(Table2()), "table2");
+
+       EXPECT_EQ(database.getColumnName(&Table1::column1), "table1.column1");
+       EXPECT_EQ(database.getColumnName(&Table1::column2), "table1.column2");
+       EXPECT_EQ(database.getColumnName(&Table1::column3), "table1.column3");
+
+       EXPECT_EQ(database.getColumnName(&Table2::column1), "table2.column1");
+       EXPECT_EQ(database.getColumnName(&Table2::column2), "table2.column2");
+       EXPECT_EQ(database.getColumnName(&Table2::column3), "table2.column3");
+       EXPECT_EQ(database.getColumnName(&Table2::column4), "table2.column4");
+       EXPECT_EQ(database.getColumnName(&Table2::column5), "table2.column5");
+}
+
+TEST(DatabaseTests, get_names)
+{
+       auto columns = database.getColumnNames(&Table1::column1, &Table2::column3);
+       auto tables = database.getTableNames(&Table1::column1, &Table2::column1, &Table2::column1);
+       if (columns.size() == 2 && tables.size() == 2) {
+               EXPECT_EQ(columns[0], "table1.column1");
+               EXPECT_EQ(columns[1], "table2.column3");
+
+               EXPECT_EQ(tables[0], "table1");
+               EXPECT_EQ(tables[1], "table2");
+       } else {
+               EXPECT_TRUE(false);
+       }
+}