141 std::conditional_t<SelectAll,
142 std::conditional_t<Single, T, std::vector<T>>,
143 std::conditional_t<Single, Row, Result>>;
151 std::string columns_;
152 std::vector<Filter> filters_;
153 std::vector<JoinClause> joins_;
154 std::optional<std::uint64_t> limit_;
155 std::optional<std::uint64_t> offset_;
158 std::vector<std::pair<std::string, bool>> orders_;
160 inline void assert_column(
const std::string &colName)
const
162 for (
const typename T::MetaData &m : T::metaData_)
164 if (m.colName_ == colName)
170 "` is not in the specified table.");
179 inline std::string gen_sql(ClientType type)
const noexcept
182 const auto placeholder = [type, &pCount]() {
184 return type == ClientType::PostgreSQL ?
"$" + std::to_string(pCount)
188 std::string sql =
"select " + columns_ +
" from " + from_;
189 for (
const auto &join : joins_)
191 sql +=
" " + to_join_string(join.type) +
" " + join.table +
" ON " +
192 join.onLeft +
" = " + join.onRight;
194 if (!filters_.empty())
196 sql +=
" where " + filters_[0].column +
" " +
197 to_string(filters_[0].op) +
" " + placeholder() +
"";
198 for (
int i = 1; i < filters_.size(); ++i)
200 sql +=
" and " + filters_[i].column +
" " +
201 to_string(filters_[i].op) +
" " + placeholder() +
"";
204 if (!orders_.empty())
206 sql +=
" order by " + orders_[0].first +
" " +
207 std::string(orders_[0].second ?
"asc" :
"desc");
208 for (
int i = 1; i < orders_.size(); ++i)
210 sql +=
", " + orders_[i].first +
" " +
211 std::string(orders_[i].second ?
"asc" :
"desc");
214 if (limit_.has_value())
216 sql +=
" limit " + std::to_string(limit_.value());
218 if (offset_.has_value())
220 sql +=
" offset " + std::to_string(offset_.value());
225 inline std::vector<std::string> gen_args()
const noexcept
227 std::vector<std::string> args;
228 if (!filters_.empty())
230 for (
const Filter &f : filters_)
232 args.emplace_back(f.value);
239 static ResultType convert_result(
const Result &r)
241 if constexpr (SelectAll)
243 if constexpr (Single)
250 for (
const Row &row : r)
252 ret.emplace_back(T(row));
259 if constexpr (Single)
270 inline ResultType execSync(
const DbClientPtr &client)
274 auto binder = *client << gen_sql(client->type());
275 for (
const std::string &a : gen_args())
279 binder << Mode::Blocking;
280 binder >> [&r](
const Result &result) { r = result; };
283 return convert_result(r);
286 template <
typename TFn,
typename EFn>
287 void execAsync(
const DbClientPtr &client,
289 EFn &&exceptCallback)
noexcept
291 auto binder = *client << gen_sql(client->type());
292 for (
const std::string &a : gen_args())
296 binder >> std::forward<TFn>(rCallback);
297 binder >> std::forward<EFn>(exceptCallback);
300 inline std::future<ResultType> execAsyncFuture(
301 const DbClientPtr &client)
noexcept
303 auto binder = *client << gen_sql(client->type());
304 for (
const std::string &a : gen_args())
308 std::shared_ptr<std::promise<ResultType>> prom =
309 std::make_shared<std::promise<ResultType>>();
311 [prom](
const Result &r) { prom->set_value(convert_result(r)); };
313 [prom](
const std::exception_ptr &e) { prom->set_exception(e); };
315 return prom->get_future();