Lightweight 0.20261105.1
Loading...
Searching...
No Matches
Error.hpp
1// SPDX-License-Identifier: Apache-2.0
2
3#pragma once
4
5#include <cstdint>
6#include <expected>
7#include <format>
8#include <stdexcept>
9#include <string_view>
10
11namespace Lightweight
12{
13
14/// @brief Why a relation could not provide its record(s).
15///
16/// Returned by the relation accessors (`BelongsTo::Record()`, `HasMany::All()`, `HasMany::Count()`, ...)
17/// through @ref RelationResult instead of throwing.
18///
19/// @ingroup DataMapper
20enum class RelationError : std::uint8_t
21{
22 /// No loader is installed and nothing was loaded: the record was built by hand, or read with
23 /// `DataMapperOptions { .loadRelations = false }`.
25
26 /// There is nothing to load: the foreign key is NULL, or the referenced row does not exist.
28
29 /// The default connection string changed since the record was read (see
30 /// @c SqlConnection::SetDefaultConnectionString), so the record belongs to a database the
31 /// application has switched away from. No query is attempted. Re-read the record, or load its
32 /// relations before switching.
34
35 /// The load query failed (lost connection, missing table, ...). The driver's diagnostic is reported
36 /// through @c SqlLogger. Unlike the other errors this one is not remembered: the next access retries.
38};
39
40/// @brief The outcome of a relation access: the requested value, or why it is unavailable.
41///
42/// @ingroup DataMapper
43template <typename T>
44using RelationResult = std::expected<T, RelationError>;
45
46/// @return The name of @p error, e.g. `"Outdated"`.
47constexpr std::string_view to_string(RelationError error) noexcept
48{
49 switch (error)
50 {
52 return "NotConfigured";
54 return "NotFound";
56 return "Outdated";
58 return "QueryFailed";
59 }
60 return "Unknown";
61}
62
63/// @brief Raised by the relation shortcuts that cannot return a @ref RelationResult - `operator->`,
64/// `operator*`, `begin()`/`end()`, `At()` and `operator[]` - when the relation is unavailable.
65///
66/// Prefer the accessors returning @ref RelationResult (`Record()`, `All()`, `Count()`, ...) to handle
67/// the unavailable case without exceptions.
68///
69/// @ingroup DataMapper
70class SqlRequireLoadedError: public std::runtime_error
71{
72 public:
73 /// Constructs the error with the name of the column type that failed to load.
74 ///
75 /// @param columnType The relation type, for the message.
76 /// @param error Why it failed.
77 explicit SqlRequireLoadedError(std::string_view columnType, RelationError error = RelationError::NotConfigured):
78 std::runtime_error(std::format("Could not load the data record: {} ({})", columnType, to_string(error))),
79 _error { error }
80 {
81 }
82
83 /// @return Why the relation could not be loaded.
84 [[nodiscard]] RelationError Error() const noexcept
85 {
86 return _error;
87 }
88
89 private:
90 RelationError _error;
91};
92
93} // namespace Lightweight
94
95/// Formats a @ref Lightweight::RelationError by name.
96template <>
97struct std::formatter<Lightweight::RelationError>: std::formatter<std::string_view>
98{
99 /// Formats @p error as its name.
100 auto format(Lightweight::RelationError error, std::format_context& ctx) const
101 {
102 return std::formatter<std::string_view>::format(Lightweight::to_string(error), ctx);
103 }
104};
Raised by the relation shortcuts that cannot return a RelationResult - operator->,...
Definition Error.hpp:71
SqlRequireLoadedError(std::string_view columnType, RelationError error=RelationError::NotConfigured)
Definition Error.hpp:77
RelationError Error() const noexcept
Definition Error.hpp:84
std::expected< T, RelationError > RelationResult
The outcome of a relation access: the requested value, or why it is unavailable.
Definition Error.hpp:44
RelationError
Why a relation could not provide its record(s).
Definition Error.hpp:21
@ NotFound
There is nothing to load: the foreign key is NULL, or the referenced row does not exist.