5#include "../DataBinder/Core.hpp"
6#include "../DataBinder/SqlNullValue.hpp"
7#include "../SqlStatement.hpp"
8#include "BelongsTo.hpp"
13#include <reflection-cpp/reflection.hpp>
63template <
typename OtherRecord, auto TheInverseSelector = AutoDetectRelation>
67 "The second template argument of HasMany must be a foreign key column name (a SqlRealName) "
68 "or std::nullopt to resolve the relationship automatically.");
84 using iterator = ReferencedRecordList::iterator;
107 template <
typename Callable>
108 void Each(Callable
const& callable);
121 return _records ? &*_records :
nullptr;
125 [[nodiscard]] std::size_t
Count() const noexcept;
135 [[nodiscard]] OtherRecord const&
At(std::
size_t index) const;
142 [[nodiscard]] OtherRecord&
At(std::
size_t index);
149 [[nodiscard]] OtherRecord const& operator[](std::
size_t index) const;
156 [[nodiscard]] OtherRecord& operator[](std::
size_t index);
172 constexpr std::weak_ordering operator<=>(
HasMany const& other) const noexcept = default;
174 constexpr
bool operator==(
HasMany const& other) const noexcept = default;
176 constexpr
bool operator!=(
HasMany const& other) const noexcept = default;
180 std::function<size_t()> count {};
184 std::weak_ordering
operator<=>(Loader
const& )
const noexcept
186 return std::weak_ordering::equivalent;
194 void RequireLoaded();
197 std::optional<ReferencedRecordList> _records;
198 std::optional<size_t> _count;
203 template <
typename T>
204 struct IsHasManyType: std::false_type
208 template <
typename OtherRecord, auto InverseSelector>
209 struct IsHasManyType<HasMany<OtherRecord, InverseSelector>>: std::true_type
216constexpr bool IsHasMany = detail::IsHasManyType<std::remove_cvref_t<T>>::value;
218template <
typename OtherRecord, auto InverseSelector>
221 _loader = std::move(loader);
224template <
typename OtherRecord, auto InverseSelector>
235 _records = _loader.all();
241template <
typename OtherRecord, auto InverseSelector>
246 _records = { std::move(records) };
250template <
typename OtherRecord, auto InverseSelector>
252 InverseSelector>::All()
258template <
typename OtherRecord, auto InverseSelector>
259template <
typename Callable>
262 if (!_records && _loader.each)
264 _loader.each(callable);
268 for (
auto const& record: All())
272template <
typename OtherRecord, auto InverseSelector>
275 InverseSelector>::All()
const
277 const_cast<HasMany*
>(
this)->RequireLoaded();
281template <
typename OtherRecord, auto InverseSelector>
285 return _records->size();
287 if (!_count && _loader.count)
290 return _count.value_or(0);
293template <
typename OtherRecord, auto InverseSelector>
299template <
typename OtherRecord, auto InverseSelector>
302 const_cast<HasMany*
>(
this)->RequireLoaded();
303 return *_records->at(index);
306template <
typename OtherRecord, auto InverseSelector>
310 return *_records->at(index);
313template <
typename OtherRecord, auto InverseSelector>
316 const_cast<HasMany*
>(
this)->RequireLoaded();
317 return *(*_records)[index];
320template <
typename OtherRecord, auto InverseSelector>
324 return *(*_records)[index];
327template <
typename OtherRecord, auto InverseSelector>
329 InverseSelector>::begin()
332 return _records->begin();
335template <
typename OtherRecord, auto InverseSelector>
339 return _records->end();
342template <
typename OtherRecord, auto InverseSelector>
344 InverseSelector>::begin()
const
346 const_cast<HasMany*
>(
this)->RequireLoaded();
347 return _records->
begin();
350template <
typename OtherRecord, auto InverseSelector>
352 InverseSelector>::end()
const
354 const_cast<HasMany*
>(
this)->RequireLoaded();
355 return _records->
end();
This HasMany<OtherRecord> represents a simple one-to-many relationship between two records.
OtherRecord const & At(std::size_t index) const
Retrieves the record at the given index.
ReferencedRecordList::iterator iterator
Iterator type for the list of records.
void Each(Callable const &callable)
Iterates over the list of records and calls the given callable for each record.
constexpr std::weak_ordering operator<=>(HasMany const &other) const noexcept=default
Three-way comparison operator.
ReferencedRecordList::const_iterator const_iterator
Const iterator type for the list of records.
ReferencedRecordList * LoadedRecords() noexcept
Returns the already-loaded records, or nullptr when the relation is not loaded.
OtherRecord ReferencedRecord
The record type of the "many" side of the relationship.
std::size_t Count() const noexcept
Retrieves the number of records in this 1-to-many relationship.
OtherRecord const & operator[](std::size_t index) const
Retrieves the record at the given index.
ReferencedRecordList & All()
Retrieves the list of records as mutable reference.
OtherRecord value_type
Record type of the "many" side of the relationship.
void SetAutoLoader(Loader loader) noexcept
Used internally to configure on-demand loading of the records.
static constexpr auto InverseSelector
Singles out the foreign key of OtherRecord that backs this relationship.
std::vector< std::shared_ptr< OtherRecord > > ReferencedRecordList
The list of records on the "many" side of the relationship.
bool IsEmpty() const noexcept
Checks if this 1-to-many relationship is empty.
ReferencedRecordList const & All() const
Retrieves the list of loaded records.
ReferencedRecordList & Emplace(ReferencedRecordList &&records) noexcept
Emplaces the given list of records.
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.
@ Count
Number of enumerators; not an operation itself.