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);
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>
}
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 ";
{
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 << " ";
{
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 << " (";
{
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;
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>
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);
}
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;
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) {
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;
}
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;
}
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) {
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;
}
--- /dev/null
+/*
+ * 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);
+ }
+}