Lightweight 0.20261105.1
Loading...
Searching...
No Matches
RelationLoadSource.hpp
1// SPDX-License-Identifier: Apache-2.0
2
3#pragma once
4
5#include "../Api.hpp"
6#include "../SqlConnectInfo.hpp"
7#include "Error.hpp"
8
9#include <cstdint>
10#include <memory>
11
12namespace Lightweight
13{
14
15class DataMapper;
16
17namespace detail
18{
19 /// Where the lazy relation loaders of a record obtain the data mapper they run their query on.
20 ///
21 /// Every data mapper carries one and hands it to the loaders it installs, which keep it alive by
22 /// shared ownership. @c Borrow() is called from exactly one place: the loader lambdas that
23 /// @c DataMapper::ConfigureRelationAutoLoading installs, when a relation is first touched.
24 ///
25 /// Implementations:
26 /// - @c Pool::PoolRelationLoadSource (Pool.hpp) - attached by @c Pool::MakeEntry to every mapper the
27 /// pool creates, via @ref AdoptRelationLoadSource; borrows from that pool.
28 /// - @c GlobalPoolLoadSource (DataMapper.cpp) - chosen by @c DataMapper::RelationLoadSourceForLoaders
29 /// for a plain mapper on the default connection string; forwards to @ref GlobalDataMapperPool.
30 /// - @c ConnectionStringLoadSource (DataMapper.cpp) - chosen for a plain mapper on any other
31 /// connection string; reconnects with it.
32 /// - @c DefaultPinnedLoadSource (DataMapper.cpp) - wraps the first two, see
33 /// @ref PinToDefaultConnectionString. A record may therefore outlive the mapper - or pool lease - it was read
34 /// through, and still load its relations from the same database: a pooled mapper's source borrows
35 /// from its pool, and a plain mapper's source reconnects with its connection string.
36 class RelationLoadSource
37 {
38 public:
39 RelationLoadSource() = default;
40 RelationLoadSource(RelationLoadSource const&) = delete;
41 RelationLoadSource(RelationLoadSource&&) = delete;
42 RelationLoadSource& operator=(RelationLoadSource const&) = delete;
43 RelationLoadSource& operator=(RelationLoadSource&&) = delete;
44 virtual ~RelationLoadSource() = default;
45
46 /// Borrows a data mapper for one load.
47 ///
48 /// Held exclusively until the last copy of the returned pointer is released, which gives the
49 /// mapper back to where it came from (a pool, or this source), so no two loads ever share its
50 /// connection or statement.
51 ///
52 /// @return The borrowed mapper (never null); @ref RelationError::Outdated when the records this
53 /// source serves belong to a default connection string the application has switched
54 /// away from; @ref RelationError::QueryFailed when connecting failed.
55 [[nodiscard]] virtual RelationResult<std::shared_ptr<DataMapper>> Borrow() = 0;
56 };
57
58 /// Wraps @p inner, a source that follows the default connection string (a pool), so that it only
59 /// serves records read while the default was @p connectionString.
60 ///
61 /// @param inner The default-following source to borrow from.
62 /// @param connectionString The connection string the records' mapper was connected with.
63 /// @param generation The @ref SqlConnection::DefaultConnectionStringGeneration that string was
64 /// current under; lets an unchanged default skip the string comparison.
65 /// @return A source whose @c Borrow() reports @ref RelationError::Outdated - without connecting -
66 /// once the default no longer is @p connectionString.
67 [[nodiscard]] LIGHTWEIGHT_API std::shared_ptr<RelationLoadSource> PinToDefaultConnectionString(
68 std::shared_ptr<RelationLoadSource> inner, SqlConnectionString connectionString, std::uint32_t generation);
69
70 /// Makes @p source the relation-load source of @p dataMapper, for the records it reads from now on.
71 ///
72 /// Used by whatever owns a data mapper on behalf of others - a pool - so that records read through
73 /// it load their relations from the same owner.
74 ///
75 /// @param dataMapper The mapper to configure.
76 /// @param source The source its auto-loaders will borrow from; null restores the default choice.
77 inline void AdoptRelationLoadSource(DataMapper& dataMapper, std::shared_ptr<RelationLoadSource> source) noexcept;
78} // namespace detail
79
80} // namespace Lightweight