From 6fa56fbe9857d8d8f32f753a6ebd1754c8bf50e5 Mon Sep 17 00:00:00 2001 From: Sangwan Kwon Date: Thu, 23 Jan 2020 15:26:09 +0900 Subject: [PATCH] c++17: Refactor table with class type deduction Signed-off-by: Sangwan Kwon --- src/vist/CMakeLists.txt | 1 + src/vist/query-builder/CMakeLists.txt | 2 +- src/vist/query-builder/column-pack.hpp | 85 +++++++++++++------------------- src/vist/query-builder/column.hpp | 6 ++- src/vist/query-builder/crud.hpp | 2 +- src/vist/query-builder/table.hpp | 2 +- src/vist/query-builder/tests/columns.cpp | 62 +++++++++++++++++++++++ 7 files changed, 105 insertions(+), 55 deletions(-) create mode 100644 src/vist/query-builder/tests/columns.cpp diff --git a/src/vist/CMakeLists.txt b/src/vist/CMakeLists.txt index 4208e76..dcecc0d 100644 --- a/src/vist/CMakeLists.txt +++ b/src/vist/CMakeLists.txt @@ -49,6 +49,7 @@ ADD_SUBDIRECTORY(database) ADD_SUBDIRECTORY(event) ADD_SUBDIRECTORY(klass) ADD_SUBDIRECTORY(logger) +ADD_SUBDIRECTORY(query-builder) ADD_SUBDIRECTORY(sdk) # rmi diff --git a/src/vist/query-builder/CMakeLists.txt b/src/vist/query-builder/CMakeLists.txt index 3965ab0..7220d8f 100644 --- a/src/vist/query-builder/CMakeLists.txt +++ b/src/vist/query-builder/CMakeLists.txt @@ -14,6 +14,6 @@ ADD_VIST_COMMON_LIBRARY(vist_query_builder query-builder.cpp) -/// TSQB: Type Safe Query Builder +# TSQB: Type Safe Query Builder FILE(GLOB TSQB_TESTS "tests/*.cpp") ADD_VIST_TEST(${TSQB_TESTS}) diff --git a/src/vist/query-builder/column-pack.hpp b/src/vist/query-builder/column-pack.hpp index 6f4e66f..7c759f3 100644 --- a/src/vist/query-builder/column-pack.hpp +++ b/src/vist/query-builder/column-pack.hpp @@ -16,79 +16,62 @@ #pragma once +#include "tuple-helper.hpp" #include "type.hpp" #include +#include #include namespace vist { namespace tsqb { namespace internal { -template -class ColumnPack { +template +class ColumnPack final { public: - virtual ~ColumnPack() = default; + using TableType = typename std::tuple_element<0, std::tuple>::type::TableType; + using TupleType = std::tuple; - template - std::string getName(ColumnType&&) const noexcept { return std::string(); } - std::vector getNames(void) const noexcept { return {}; } + explicit ColumnPack(Columns&& ...columns) : columns(columns...) + { + } - int size() const noexcept { return 0; } -}; + template + 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; + }; -template -class ColumnPack : public ColumnPack { -public: - using Column = Front; - using TableType = typename Column::TableType; + tuple_helper::for_each(this->columns, predicate); - explicit ColumnPack(Front&& front, Rest&& ...rest); - virtual ~ColumnPack() = default; + return name; + } - ColumnPack(const ColumnPack&) = delete; - ColumnPack& operator=(const ColumnPack&) = delete; + std::vector getNames(void) const noexcept + { + std::vector names; + auto closure = [&names](const auto& iter) { + names.push_back(iter.name); + }; - ColumnPack(ColumnPack&&) = default; - ColumnPack& operator=(ColumnPack&&) = default; + tuple_helper::for_each(this->columns, closure); - template - std::string getName(ColumnType&& type) const noexcept; - std::vector getNames(void) const noexcept; + return names; + } - int size() const noexcept { return Base::size() + 1; } + std::size_t size() const noexcept + { + return std::tuple_size::value; + } private: - using Base = ColumnPack; - - Column column; + std::tuple columns; }; -template -ColumnPack::ColumnPack(Front&& front, Rest&& ...rest) : - Base(std::forward(rest)...), column(front) -{ -} - -template -std::vector ColumnPack::getNames(void) const noexcept -{ - auto names = Base::getNames(); - names.push_back(this->column.name); - - return std::move(names); -} - -template -template -std::string ColumnPack::getName(ColumnType&& type) const noexcept -{ - if (type::cast_compare(column.type, std::forward(type))) - return column.name; - - return Base::template getName(std::forward(type)); -} - } // namespace internal } // namespace tsqb } // namespace vist diff --git a/src/vist/query-builder/column.hpp b/src/vist/query-builder/column.hpp index 5ec7aba..70b1c75 100644 --- a/src/vist/query-builder/column.hpp +++ b/src/vist/query-builder/column.hpp @@ -23,11 +23,15 @@ namespace vist { namespace tsqb { template -struct Column { +struct Column final { using Type = Field Object::*; using FieldType = Field; using TableType = Object; + Column(const std::string& name, Field Object::*field) : name(name), type(field) + { + } + std::string name; Type type; }; diff --git a/src/vist/query-builder/crud.hpp b/src/vist/query-builder/crud.hpp index bfba587..ded5080 100644 --- a/src/vist/query-builder/crud.hpp +++ b/src/vist/query-builder/crud.hpp @@ -124,7 +124,7 @@ T& Crud::selectInternal(ColumnTuple&& ct, bool distinct) if (distinct) ss << "DISTINCT "; - int i = 0; + std::size_t i = 0; for (const auto& c : columnNames) { ss << c; diff --git a/src/vist/query-builder/table.hpp b/src/vist/query-builder/table.hpp index 9bdafad..fe7e208 100644 --- a/src/vist/query-builder/table.hpp +++ b/src/vist/query-builder/table.hpp @@ -102,7 +102,7 @@ Table::Table(const std::string& name, ColumnPackType&& columnPack) template template -std::set Table::getTableNames(Cs&& tuple) const noexcept +std::set Table::getTableNames(Cs&&) const noexcept { return {this->name}; } diff --git a/src/vist/query-builder/tests/columns.cpp b/src/vist/query-builder/tests/columns.cpp new file mode 100644 index 0000000..23ddc4e --- /dev/null +++ b/src/vist/query-builder/tests/columns.cpp @@ -0,0 +1,62 @@ +/* + * 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 + +#include +#include + +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); +} -- 2.7.4