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, ///< Ouput 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}}, log_mode_{log_mode} {}
68
69 Query(const char* statement, std::optional<Name> name = std::nullopt, LogMode log_mode = LogMode::kFull)
70 : Query(std::string{statement}, std::move(name), log_mode) {}
71 Query(std::string statement, std::optional<Name> name = std::nullopt, LogMode log_mode = LogMode::kFull)
72 : data_{DynamicStrings{std::move(statement), std::move(name)}}, log_mode_(log_mode) {}
73
74 /// @returns view to the query name that is alive as long as *this is alive
75 std::optional<NameView> GetOptionalNameView() const noexcept;
76
77 /// @returns optional queury name suitable for construction of a new Query
78 std::optional<Name> GetOptionalName() const { return std::optional<Name>{GetOptionalNameView()}; }
79
80 /// @returns zero terminated view to the statement that is alive as long as *this is alive
82
83 /// @returns logging mode
84 LogMode GetLogMode() const noexcept { return log_mode_; }
85
86private:
87 struct DynamicStrings {
88 std::string statement_;
89 std::optional<Name> name_;
90 };
91 struct StaticStrings {
92 utils::StringLiteral statement_;
93 std::optional<NameLiteral> name_;
94 };
95 struct NameViewVisitor;
96
97 std::variant<StaticStrings, DynamicStrings> data_ = StaticStrings{utils::StringLiteral{""}, std::nullopt};
98 LogMode log_mode_ = LogMode::kFull;
99};
100
101} // namespace storages
102
103USERVER_NAMESPACE_END