2 * Copyright (c) 2017-present Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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
20 #include "condition.hpp"
22 #include "expression.hpp"
35 template<typename... Tables>
36 class Database : public Crud<Database<Tables...>> {
38 using Self = Database<Tables...>;
40 explicit Database(const std::string& name, Tables ...tables) :
41 name(name), tables(tables...) {}
43 template<typename Table>
44 Self& join(condition::Join type = condition::Join::INNER);
46 template<typename Expr>
49 std::size_t size() const noexcept;
51 operator std::string();
55 public: // CRTP(Curiously Recurring Template Pattern) for CRUD
56 template<typename... Cs>
57 std::vector<std::string> getTableNames(Cs&& ...columns) const noexcept;
58 template<typename Table>
59 std::string getTableName(Table&& table) const noexcept;
60 template<typename... Cs>
61 std::vector<std::string> getColumnNames(Cs&& ...columns) const noexcept;
62 template<typename Column>
63 std::string getColumnName(Column&& column) const noexcept;
65 std::vector<std::string> cache;
68 std::tuple<Tables...> tables;
71 template<typename... Tables>
72 template<typename Table>
73 Database<Tables...>& Database<Tables...>::join(condition::Join type)
76 ss << condition::to_string(type) << " ";
78 ss << this->getTableName(Table());
80 this->cache.emplace_back(ss.str());
84 template<typename... Tables>
85 template<typename Expr>
86 Database<Tables...>& Database<Tables...>::on(Expr expr)
91 auto lname = this->getColumnName(std::move(expr.l.type));
94 ss << std::string(expr) << " ";
96 auto rname = this->getColumnName(std::move(expr.r.type));
99 this->cache.emplace_back(ss.str());
103 template<typename... Tables>
104 Database<Tables...>::operator std::string()
106 std::stringstream ss;
107 for (const auto& c : cache)
111 return util::rtrim(ss.str());
114 template<typename... Tables>
115 template<typename... Cs>
116 std::vector<std::string> Database<Tables...>::getTableNames(Cs&& ...columns) const noexcept
118 std::set<std::string> names;
120 auto predicate = [this, &names](const auto& column) {
121 using ColumnType = std::remove_reference_t<decltype(column)>;
122 using TableType = typename ColumnType::Table;
123 auto name = this->getTableName(TableType());
128 auto closure = [&predicate](const auto&... iter) {
129 (predicate(iter), ...);
132 std::apply(closure, std::tuple(columns...));
134 return std::vector<std::string>(names.begin(), names.end());
137 template<typename... Tables>
138 template<typename... Cs>
139 std::vector<std::string> Database<Tables...>::getColumnNames(Cs&& ...columns) const noexcept
141 std::vector<std::string> names;
142 auto predicate = [this, &names](const auto& column) {
143 auto name = this->getColumnName(column);
145 names.emplace_back(name);
148 auto closure = [&predicate](const auto&... iter) {
149 (predicate(iter), ...);
152 std::apply(closure, std::tuple(columns...));
157 template<typename... Tables>
158 template<typename Table>
159 std::string Database<Tables...>::getTableName(Table&& table) const noexcept
162 auto predicate = [&name, &table](const auto& type) {
163 if (type.compare(table))
167 auto closure = [&predicate](const auto&... iter) {
168 (predicate(iter), ...);
171 std::apply(closure, this->tables);
176 template<typename... Tables>
177 template<typename Column>
178 std::string Database<Tables...>::getColumnName(Column&& column) const noexcept
180 using ColumnType = std::remove_reference_t<decltype(column)>;
181 using TableType = typename ColumnType::Table;
185 auto predicate = [&name, &table, &column](const auto& iter) {
186 if (iter.compare(table)) {
187 auto cname = iter.getColumnName(column);
188 name = iter.name + "." + cname;
192 auto closure = [&predicate](const auto&... iter) {
193 (predicate(iter), ...);
196 std::apply(closure, this->tables);
201 template<typename... Tables>
202 std::size_t Database<Tables...>::size() const noexcept
204 using TupleType = std::tuple<Tables...>;
205 return std::tuple_size<TupleType>::value;