struct Column final {
using Type = Field Object::*;
using FieldType = Field;
- using TableType = Object;
+ using Table = Object;
Column(const std::string& name, Field Object::*field) : name(name), type(field)
{
void operator()(T&& type)
{
auto column = make_column("anonymous", type);
- using TableType = typename decltype(column)::TableType;
+ using TableType = typename decltype(column)::Table;
auto name = this->tablePack.getName(TableType());
if (!name.empty())
names.emplace(name);
#pragma once
-#include <vector>
+#include "tuple-helper.hpp"
+
#include <set>
#include <string>
+#include <tuple>
+#include <vector>
namespace vist {
namespace tsqb {
namespace internal {
-template<typename... Base>
-class TablePack {
+template<typename... Tables>
+class TablePack final {
public:
- virtual ~TablePack() = default;
+ using TupleType = std::tuple<Tables...>;
- template<typename TableType>
- std::string getName(TableType&&) const noexcept { return std::string(); }
-
- template<typename ColumnType>
- std::string getColumnName(ColumnType&&) const noexcept { return std::string(); }
-};
-
-template<typename Front, typename... Rest>
-class TablePack<Front, Rest...> : public TablePack<Rest...> {
-public:
- using Table = Front;
-
- explicit TablePack(Front&& front, Rest&& ...rest);
- virtual ~TablePack() = default;
+ explicit TablePack(Tables ...tables) : tables(tables...)
+ {
+ }
- TablePack(const TablePack&) = delete;
- TablePack& operator=(const TablePack&) = delete;
+ 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;
+ };
- TablePack(TablePack&&) = default;
- TablePack& operator=(TablePack&&) = default;
+ tuple_helper::for_each(this->tables, predicate);
- template<typename TableType>
- std::string getName(TableType&& table) const noexcept;
+ return name;
+ }
template<typename ColumnType>
- std::string getColumnName(ColumnType&& column) const noexcept;
+ 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:
- using Base = TablePack<Rest...>;
-
- Table table;
+ std::tuple<Tables...> tables;
};
-template<typename Front, typename... Rest>
-TablePack<Front, Rest...>::TablePack(Front&& front, Rest&& ...rest) :
- Base(std::forward<Rest>(rest)...), table(front)
-{
-}
-
-template<typename Front, typename... Rest>
-template<typename TableType>
-std::string TablePack<Front, Rest...>::getName(TableType&& table) const noexcept
-{
- if (this->table.compare(table))
- return this->table.name;
-
- return Base::template getName<TableType>(std::forward<TableType>(table));
-}
-
-template<typename Front, typename... Rest>
-template<typename ColumnType>
-std::string TablePack<Front, Rest...>::getColumnName(ColumnType&& column) const noexcept
-{
- using DecayColumnType = typename std::decay<ColumnType>::type;
- using DecayTableType = typename DecayColumnType::TableType;
- if (this->table.compare(DecayTableType())) {
- auto cname = this->table.getColumnName(column.type);
- return this->table.name + "." + cname;
- }
-
- return Base::template getColumnName<ColumnType>(std::forward<ColumnType>(column));
-}
-
} // namespace internal
} // namespace tsqb
} // namespace vist
#pragma once
-#include "crud.hpp"
#include "column.hpp"
-#include "column-pack.hpp"
+#include "crud.hpp"
#include "tuple-helper.hpp"
+#include "type.hpp"
#include "util.hpp"
-#include <vector>
-#include <string>
#include <sstream>
+#include <string>
+#include <tuple>
+#include <vector>
namespace vist {
namespace tsqb {
template<typename... Columns>
class Table : public Crud<Table<Columns...>> {
public:
- virtual ~Table() = default;
+ /// Make first stuct type to table type
+ using Type = typename std::tuple_element<0, std::tuple<Columns...>>::type::Table;
- Table(const Table&) = delete;
- Table& operator=(const Table&) = delete;
-
- Table(Table&&) = default;
- Table& operator=(Table&&) = default;
-
- // 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 That>
- std::string getTableName(That&& type) const noexcept;
- template<typename ColumnType>
- std::string getColumnName(ColumnType&& type) const noexcept;
+ explicit Table(const std::string& name, Columns&& ...columns) :
+ name(name), columns(columns...) {}
+ std::string getName(void) const noexcept;
std::vector<std::string> getColumnNames(void) const noexcept;
template<typename That>
bool compare(const That& that) const noexcept;
- int size() const noexcept;
+ std::size_t size() const noexcept;
operator std::string();
- std::string name;
- std::vector<std::string> cache;
+ const std::string name;
-private:
- using ColumnPackType = internal::ColumnPack<Columns...>;
- using TableType = typename ColumnPackType::TableType;
+public: // CRTP(Curiously Recurring Template Pattern) for CRUD
+ template<typename Cs>
+ std::set<std::string> getTableNames(Cs&& tuple) 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 Column>
+ std::string getColumnName(const Column& column) const noexcept;
- explicit Table(const std::string& name, ColumnPackType&& columnPack);
+ std::vector<std::string> cache;
+private:
template<typename ...Cs>
friend Table<Cs...> make_table(const std::string& name, Cs&& ...columns);
- struct GetColumnNames {
- const ColumnPackType& columnPack;
- std::vector<std::string> names;
-
- GetColumnNames(const ColumnPackType& columnPack) : columnPack(columnPack) {}
-
- template <typename T>
- void operator()(T&& type)
- {
- auto name = this->columnPack.getName(std::forward<T>(type));
- if (!name.empty())
- names.emplace_back(name);
- }
- };
-
- ColumnPackType columnPack;
+ std::tuple<Columns...> columns;
};
template<typename ...Columns>
Table<Columns...> make_table(const std::string& name, Columns&& ...cs)
{
- auto columnPack = internal::ColumnPack<Columns...>(std::forward<Columns>(cs)...);
- return Table<Columns...>(name, std::move(columnPack));
+ return Table<Columns...>(name, std::forward<Columns>(cs)...);
}
template<typename... Columns>
-Table<Columns...>::Table(const std::string& name, ColumnPackType&& columnPack)
- : name(name), columnPack(std::move(columnPack)) {}
+std::string Table<Columns...>::getName() const noexcept
+{
+ return this->name;
+}
template<typename... Columns>
template<typename Cs>
template<typename Cs>
std::vector<std::string> Table<Columns...>::getColumnNames(Cs&& tuple) const noexcept
{
- GetColumnNames closure(this->columnPack);
+ std::vector<std::string> names;
+ auto closure = [this, &names](auto type) {
+ auto name = this->getColumnName(type);
+ if (!name.empty())
+ names.emplace_back(name);
+ };
+
tuple_helper::for_each(std::forward<Cs>(tuple), closure);
- return closure.names;
+ return names;
}
template<typename... Columns>
template<typename That>
-std::string Table<Columns...>::getTableName(That&& type) const noexcept
+std::string Table<Columns...>::getTableName(That&&) const noexcept
{
return this->name;
}
template<typename... Columns>
-template<typename ColumnType>
-std::string Table<Columns...>::getColumnName(ColumnType&& type) const noexcept
+std::vector<std::string> Table<Columns...>::getColumnNames(void) const noexcept
{
- return this->columnPack.getName(std::forward<ColumnType>(type));
+ 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;
}
template<typename... Columns>
-std::vector<std::string> Table<Columns...>::getColumnNames(void) const noexcept
+template<typename Column>
+std::string Table<Columns...>::getColumnName(const Column& column) const noexcept
{
- return this->columnPack.getNames();
+ 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;
}
template<typename... Columns>
template<typename That>
bool Table<Columns...>::compare(const That& that) const noexcept
{
- using This = TableType;
+ using This = Type;
return type::compare(This(), that);
}
}
template<typename... Columns>
-int Table<Columns...>::size() const noexcept
+std::size_t Table<Columns...>::size() const noexcept
{
- return this->columnPack.size();
+ using TupleType = std::tuple<Columns...>;
+ return std::tuple_size<TupleType>::value;
}
} // namespace tsqb
+++ /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-pack.hpp>
-#include <vist/query-builder/column.hpp>
-
-using namespace vist::tsqb;
-using namespace vist::tsqb::internal;
-
-namespace {
-
-struct Sample {
- int int1;
- int int2;
- std::string str1;
- std::string str2;
- bool bool1;
- bool bool2;
-};
-
-ColumnPack columns { Column("int1", &Sample::int1),
- Column("int2", &Sample::int2),
- Column("str1", &Sample::str1),
- Column("str2", &Sample::str2),
- Column("bool1", &Sample::bool1),
- Column("bool2", &Sample::bool2) };
-}
-
-TEST(ColumnTests, size)
-{
- EXPECT_EQ(columns.size(), 6);
-}
-
-TEST(ColumnTests, get_name)
-{
- EXPECT_EQ(columns.getName(&Sample::int1), "int1");
- EXPECT_EQ(columns.getName(&Sample::int2), "int2");
- EXPECT_EQ(columns.getName(&Sample::str1), "str1");
- EXPECT_EQ(columns.getName(&Sample::str2), "str2");
- EXPECT_EQ(columns.getName(&Sample::bool1), "bool1");
- EXPECT_EQ(columns.getName(&Sample::bool2), "bool2");
-}
-
-TEST(ColumnTests, get_names)
-{
- EXPECT_EQ(columns.getNames().size(), 6);
-}
--- /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/table-pack.hpp>
+#include <vist/query-builder/table.hpp>
+
+using namespace vist::tsqb;
+using namespace vist::tsqb::internal;
+
+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) };
+
+TablePack tables { table1, table2 };
+
+} // anonymous namespace
+
+TEST(TableTests, size)
+{
+ EXPECT_EQ(table1.size(), 3);
+ EXPECT_EQ(table2.size(), 5);
+}
+
+TEST(TableTests, get_name)
+{
+ EXPECT_EQ(table1.getName(), "table1");
+ EXPECT_EQ(table2.name, "table2");
+
+ EXPECT_EQ(table1.getColumnName(&Table1::column1), "column1");
+ EXPECT_EQ(table1.getColumnName(&Table1::column2), "column2");
+ EXPECT_EQ(table1.getColumnName(&Table1::column3), "column3");
+
+ EXPECT_EQ(table2.getColumnName(&Table2::column1), "column1");
+ EXPECT_EQ(table2.getColumnName(&Table2::column2), "column2");
+ EXPECT_EQ(table2.getColumnName(&Table2::column3), "column3");
+ EXPECT_EQ(table2.getColumnName(&Table2::column4), "column4");
+ EXPECT_EQ(table2.getColumnName(&Table2::column5), "column5");
+}
+
+TEST(TableTests, get_names)
+{
+ EXPECT_EQ(table1.getColumnNames().size(), 3);
+ EXPECT_EQ(table2.getColumnNames().size(), 5);
+}
+
+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");
+}