userver: userver/storages/query.hpp Source File
Loading...
Searching...
No Matches
query.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/storages/query.hpp
4/// @brief @copybrief storages::Query
5
6#include <optional>
7#include <string>
8#include <variant>
9
10#include <userver/utils/string_literal.hpp>
11#include <userver/utils/strong_typedef.hpp>
12
13USERVER_NAMESPACE_BEGIN
14
15namespace tracing {
16class Span;
17} // namespace tracing
18
19namespace storages {
20
21/// @brief Holds a query, its name and logging mode; used by all the SQL databases of userver.
22///
23/// Prefer using via @ref scripts/docs/en/userver/sql_files.md or use a const variable with `name` specified
24/// as NameLiteral.
25///
26/// @note You may write a query in `.sql` file and generate a header file with Query from it.
27/// See @ref scripts/docs/en/userver/sql_files.md for more information.
28class Query {
29public:
30 /// String with query name
31 using Name = utils::StrongTypedef<struct NameTag, std::string>;
32
33 /// Zero terminated view to the query name
34 using NameView = utils::zstring_view;
35
36 /// Compile time literal with query name
37 class NameLiteral : public utils::zstring_view {
38 public:
39 NameLiteral() = delete;
40
41#if defined(__clang__) && __clang_major__ < 18
42 // clang-16 and below lose (optimize out) the pointer to `literal` with consteval. Clang-18 is know to work
43 constexpr
44#else
45 USERVER_IMPL_CONSTEVAL
46#endif
47 NameLiteral(const char* literal) noexcept
48 : zstring_view{literal} {
49 }
50 };
51
52 enum class LogMode : unsigned char {
53 kFull, ///< Output name and optionally statement
54 kNameOnly, ///< Output only name
55 };
56
57 Query() = default;
58 ~Query() = default;
59
60 Query(const Query& other) = default;
61 Query(Query&& other) = default;
62 Query& operator=(const Query& other) = default;
63 Query& operator=(Query&& other) = default;
64
65 /// Constructor that omits dynamic initialization and relies on `statement` and `name` being string literals
66 constexpr Query(utils::StringLiteral statement, NameLiteral name, LogMode log_mode)
67 : data_{StaticStrings{statement, name}},
68 log_mode_{log_mode}
69 {}
70
71 Query(const char* statement, std::optional<Name> name = std::nullopt, LogMode log_mode = LogMode::kFull)
72 : Query(std::string{statement}, std::move(name), log_mode)
73 {}
74 Query(std::string statement, std::optional<Name> name = std::nullopt, LogMode log_mode = LogMode::kFull)
75 : data_{DynamicStrings{std::move(statement), std::move(name)}},
76 log_mode_(log_mode)
77 {}
78
79 /// @returns view to the query name that is alive as long as *this is alive
80 std::optional<NameView> GetOptionalNameView() const noexcept;
81
82 /// @returns optional queury name suitable for construction of a new Query
83 std::optional<Name> GetOptionalName() const { return std::optional<Name>{GetOptionalNameView()}; }
84
85 /// @returns zero terminated view to the statement that is alive as long as *this is alive
86 utils::zstring_view GetStatementView() const noexcept;
87
88 /// @returns logging mode
89 LogMode GetLogMode() const noexcept { return log_mode_; }
90
91private:
92 struct DynamicStrings {
93 std::string statement;
94 std::optional<Name> name;
95 };
96 struct StaticStrings {
97 utils::StringLiteral statement;
98 std::optional<NameLiteral> name;
99 };
100 struct NameViewVisitor;
101
102 std::variant<StaticStrings, DynamicStrings> data_ = StaticStrings{utils::StringLiteral{""}, std::nullopt};
103 LogMode log_mode_ = LogMode::kFull;
104};
105
106} // namespace storages
107
108USERVER_NAMESPACE_END