9#include <reflection-cpp/reflection.hpp>
50template <
typename ReferencedRecordT,
51 typename ThroughRecordT,
57 "The selector template arguments of HasManyThrough must be foreign key column names "
58 "(a SqlRealName) or std::nullopt to resolve the relationship automatically.");
79 using iterator = ReferencedRecordList::iterator;
93 [[nodiscard]] std::
size_t Count() const;
96 [[nodiscard]]
bool IsEmpty() const;
136 std::weak_ordering operator<=>(
HasManyThrough const& other) const noexcept = default;
140 std::function<size_t()> count;
148 _loader = std::move(loader);
154 _count = std::nullopt;
155 _records = std::nullopt;
164 template <
typename Callable>
165 void Each(Callable
const& callable)
167 if (!_records && _loader.each)
169 _loader.each(callable);
173 for (
auto const& record:
All())
184 _records = _loader.all();
192 std::optional<size_t> _count;
193 std::optional<ReferencedRecordList> _records;
198 template <
typename T>
199 struct IsHasManyThroughType: std::false_type
203 template <
typename ReferencedRecordT,
typename ThroughRecordT, auto OwnerSelector, auto ReferencedSelector>
204 struct IsHasManyThroughType<HasManyThrough<ReferencedRecordT, ThroughRecordT, OwnerSelector, ReferencedSelector>>:
212constexpr bool IsHasManyThrough = detail::IsHasManyThroughType<std::remove_cvref_t<T>>::value;
214template <
typename ReferencedRecordT,
typename ThroughRecordT, auto OwnerSelector, auto ReferencedSelector>
220 return _records.value();
223template <
typename ReferencedRecordT,
typename ThroughRecordT, auto OwnerSelector, auto ReferencedSelector>
229 return _records.value();
232template <
typename ReferencedRecordT,
typename ThroughRecordT, auto OwnerSelector, auto ReferencedSelector>
239 _records = { std::move(records) };
240 _count = _records->size();
244template <
typename ReferencedRecordT,
typename ThroughRecordT, auto OwnerSelector, auto ReferencedSelector>
248 return _records->size();
254 return _count.value_or(0);
257template <
typename ReferencedRecordT,
typename ThroughRecordT, auto OwnerSelector, auto ReferencedSelector>
263template <
typename ReferencedRecordT,
typename ThroughRecordT, auto OwnerSelector, auto ReferencedSelector>
267 return *All().at(index);
270template <
typename ReferencedRecordT,
typename ThroughRecordT, auto OwnerSelector, auto ReferencedSelector>
274 return *All().at(index);
277template <
typename ReferencedRecordT,
typename ThroughRecordT, auto OwnerSelector, auto ReferencedSelector>
281 return *All()[index];
284template <
typename ReferencedRecordT,
typename ThroughRecordT, auto OwnerSelector, auto ReferencedSelector>
288 return *All()[index];
291template <
typename ReferencedRecordT,
typename ThroughRecordT, auto OwnerSelector, auto ReferencedSelector>
295 return All().begin();
298template <
typename ReferencedRecordT,
typename ThroughRecordT, auto OwnerSelector, auto ReferencedSelector>
305template <
typename ReferencedRecordT,
typename ThroughRecordT, auto OwnerSelector, auto ReferencedSelector>
309 return All().begin();
312template <
typename ReferencedRecordT,
typename ThroughRecordT, auto OwnerSelector, auto ReferencedSelector>
This API represents a many-to-many relationship between two records through a third record.
ReferencedRecordList::iterator iterator
Iterator type for the list of records.
iterator end() noexcept
Returns an iterator to the end of the record list.
ReferencedRecordT ReferencedRecord
The record type of the "many" side of the relationship.
iterator begin() noexcept
Returns an iterator to the beginning of the record list.
bool IsEmpty() const
Checks if this relationship is empty.
ReferencedRecordList & Emplace(ReferencedRecordList &&records) noexcept
Emplaces the given list of records into this relationship.
static constexpr auto OwnerSelector
Singles out the join record's foreign key pointing at the record owning this relationship.
ReferencedRecord value_type
Value type for range-based iteration.
std::size_t Count() const
Retrieves the number of records in this relationship.
void Reload()
Reloads the records from the database.
ReferencedRecordList::const_iterator const_iterator
Const iterator type for the list of records.
ReferencedRecordList const & All() const noexcept
Retrieves the list of loaded records.
void SetAutoLoader(Loader loader) noexcept
Used internally to configure on-demand loading of the records.
ReferencedRecord const & operator[](std::size_t index) const
Retrieves the record at the given index.
ThroughRecordT ThroughRecord
The record type of the "through" side of the relationship.
static constexpr auto ReferencedSelector
Singles out the join record's foreign key pointing at ReferencedRecord.
std::vector< std::shared_ptr< ReferencedRecord > > ReferencedRecordList
The list of records on the "many" side of the relationship.
void Each(Callable const &callable)
Iterates over all records in this relationship.
ReferencedRecord const & At(std::size_t index) const
Retrieves the record at the given index.
Represents an error when a record is required to be loaded but is not.
Constrains what may be used to single out one of several foreign keys into the same table.
constexpr std::nullopt_t AutoDetectRelation
Selector value meaning "resolve the relationship automatically; the match must be unique".