query-builder: Refactor expression interface
[platform/core/security/vist.git] / src / vist / query-builder / database.hpp
1 /*
2  *  Copyright (c) 2017-present Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Licensed under the Apache License, Version 2.0 (the "License");
5  *  you may not use this file except in compliance with the License.
6  *  You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License
15  */
16
17 #pragma once
18
19 #include "column.hpp"
20 #include "crud.hpp"
21 #include "expression.hpp"
22 #include "util.hpp"
23
24 #include <algorithm>
25 #include <set>
26 #include <sstream>
27 #include <string>
28 #include <tuple>
29 #include <vector>
30
31 namespace vist {
32 namespace tsqb {
33
34 template<typename... Tables>
35 class Database : public Crud<Database<Tables...>> {
36 public:
37         using Self = Database<Tables...>;
38
39         explicit Database(const std::string& name, Tables ...tables) :
40                 name(name), tables(tables...) {}
41
42         std::size_t size() const noexcept;
43
44         operator std::string();
45
46         std::string name;
47
48 public: // CRTP(Curiously Recurring Template Pattern) for CRUD
49         template<typename... Cs>
50         std::vector<std::string> getTableNames(Cs&& ...columns) const noexcept;
51         template<typename Table>
52         std::string getTableName(Table&& table) const noexcept;
53         template<typename... Cs> 
54         std::vector<std::string> getColumnNames(Cs&& ...columns) const noexcept;
55         template<typename Column>
56         std::string getColumnName(Column&& column) const noexcept;
57
58         std::vector<std::string> cache;
59
60 private:
61         std::tuple<Tables...> tables;
62 };
63
64 template<typename... Tables>
65 Database<Tables...>::operator std::string()
66 {
67         std::stringstream ss;
68         for (const auto& c : cache)
69                 ss << c << " ";
70
71         this->cache.clear();
72         return util::rtrim(ss.str());
73 }
74
75 template<typename... Tables>
76 template<typename... Cs>
77 std::vector<std::string> Database<Tables...>::getTableNames(Cs&& ...columns) const noexcept
78 {
79         std::set<std::string> names;
80
81         auto predicate = [this, &names](const auto& column) {
82                 using ColumnType = std::remove_reference_t<decltype(column)>;
83                 using TableType = typename ColumnType::Table;
84                 auto name = this->getTableName(TableType());
85                 if (!name.empty())
86                                 names.emplace(name);
87         };
88
89         auto closure = [&predicate](const auto&... iter) {
90                 (predicate(iter), ...);
91         };
92
93         std::apply(closure, std::tuple(columns...));
94
95         return std::vector<std::string>(names.begin(), names.end());
96 }
97
98 template<typename... Tables>
99 template<typename... Cs>
100 std::vector<std::string> Database<Tables...>::getColumnNames(Cs&& ...columns) const noexcept
101 {
102         std::vector<std::string> names;
103         auto predicate = [this, &names](const auto& column) {
104                 auto name = this->getColumnName(column);
105                 if (!name.empty())
106                         names.emplace_back(name);
107         };
108
109         auto closure = [&predicate](const auto&... iter) {
110                 (predicate(iter), ...);
111         };
112
113         std::apply(closure, std::tuple(columns...));
114
115         return names;
116 }
117
118 template<typename... Tables>
119 template<typename Table>
120 std::string Database<Tables...>::getTableName(Table&& table) const noexcept
121 {
122         std::string name;
123         auto predicate = [&name, &table](const auto& type) {
124                 if (type.compare(table))
125                         name = type.name;
126         };
127
128         auto closure = [&predicate](const auto&... iter) {
129                 (predicate(iter), ...);
130         };
131
132         std::apply(closure, this->tables);
133
134         return name;
135 }
136
137 template<typename... Tables>
138 template<typename Column>
139 std::string Database<Tables...>::getColumnName(Column&& column) const noexcept
140 {
141         using ColumnType = std::remove_reference_t<decltype(column)>;
142         using TableType = typename ColumnType::Table;
143         TableType table;
144
145         std::string name;
146         auto predicate = [&name, &table, &column](const auto& iter) {
147                 if (iter.compare(table)) {
148                         auto cname = iter.getColumnName(column);
149                         name = iter.name + "." + cname;
150                 }
151         };
152
153         auto closure = [&predicate](const auto&... iter) {
154                 (predicate(iter), ...);
155         };
156
157         std::apply(closure, this->tables);
158
159         return name;
160 }
161
162 template<typename... Tables>
163 std::size_t Database<Tables...>::size() const noexcept
164 {
165         using TupleType = std::tuple<Tables...>;
166         return std::tuple_size<TupleType>::value;
167 }
168
169 } // namespace tsqb
170 } // namespace vist