/* * Copyright (C) 2021 Emeric Poupon * * This file is part of LMS. * * LMS is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * LMS is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with LMS. If not, see . */ #pragma once #include #include #include #include #include #include "core/ITraceLogger.hpp" #include "database/Types.hpp" namespace lms::db::utils { #define ESCAPE_CHAR_STR "\\" static inline constexpr char escapeChar{ '\\' }; std::string escapeLikeKeyword(std::string_view keywords); template void applyRange(Query& query, std::optional range) { if (range) { query.limit(static_cast(range->size)); query.offset(static_cast(range->offset)); } } template auto fetchFirstResult(const Wt::Dbo::collection& collection) { LMS_SCOPED_TRACE_DETAILED("Database", "FetchFirstResult"); return collection.begin(); } template void fetchNextResult(typename Wt::Dbo::collection::const_iterator& it) { LMS_SCOPED_TRACE_DETAILED("Database", "FetchNextResult"); it++; } template void forEachResult(const Wt::Dbo::collection& collection, Func&& func) { typename Wt::Dbo::collection::const_iterator it{ fetchFirstResult(collection) }; while (it != collection.end()) { func(*it); fetchNextResult(it); } } template struct QueryResultType; template struct QueryResultType> { using type = ResultType; }; template void forEachQueryResult(const Query& query, UnaryFunc&& func) { LMS_SCOPED_TRACE_DETAILED_WITH_ARG("Database", "ForEachQueryResult", "Query", query.asString()); forEachResult(query.resultList(), std::forward(func)); } template std::vector fetchQueryResults(const Query& query) { LMS_SCOPED_TRACE_DETAILED_WITH_ARG("Database", "FetchQueryResults", "Query", query.asString()); auto collection{ query.resultList() }; return std::vector(collection.begin(), collection.end()); } template std::vector::type> fetchQueryResults(const Query& query) { LMS_SCOPED_TRACE_DETAILED_WITH_ARG("Database", "FetchQueryResults", "Query", query.asString()); auto collection{ query.resultList() }; return std::vector::type>(collection.begin(), collection.end()); } template auto fetchQuerySingleResult(const Query& query) { LMS_SCOPED_TRACE_DETAILED_WITH_ARG("Database", "FetchQuerySingleResult", "Query", query.asString()); return query.resultValue(); } template RangeResults execRangeQuery(Query& query, const std::optional range) { RangeResults res; if (range) { res.range.offset = range->offset; applyRange(query, Range{ range->offset, range->size + 1 }); res.results.reserve(range->size); } // TODO optim useless last copy res.results = utils::fetchQueryResults(query); if (range && (res.results.size() == range->size + 1)) { res.moreResults = true; res.results.pop_back(); } res.range.size = res.results.size(); return res; } template void forEachQueryRangeResult(Query& query, std::optional range, UnaryFunc&& func) { if (range) applyRange(query, range); forEachQueryResult(query, std::forward(func)); } template void forEachQueryRangeResult(Query& query, std::optional range, bool& moreResults, UnaryFunc&& func) { using ResultType = typename QueryResultType::type; if (range) applyRange(query, Range{ range->offset, range->size + 1 }); moreResults = false; std::size_t count{}; const auto collection{ query.resultList() }; auto it{ fetchFirstResult(collection) }; while (it != collection.end()) { if (range && (count++ == static_cast(range->size))) { moreResults = true; break; } func(*it); fetchNextResult(it); } } template void executeCommand(Wt::Dbo::Session& session, std::string_view command, const Args&... args) { LMS_SCOPED_TRACE_DETAILED_WITH_ARG("Database", "ExecuteCommand", "Command", command); Wt::Dbo::Call call{ session.execute(std::string{ command }) }; (call.bind(args), ...); } Wt::WDateTime normalizeDateTime(const Wt::WDateTime& dateTime); } // namespace lms::db::utils