14#include "orm-cxx/reflection/Reflection.hpp"
19template <
typename SchemaType>
25class RelationCollection
29 using container_type = std::vector<T>;
30 using size_type =
typename container_type::size_type;
31 using iterator =
typename container_type::iterator;
32 using const_iterator =
typename container_type::const_iterator;
34 RelationCollection() =
default;
36 RelationCollection(
const RelationCollection& other)
37 : values_(other.values_ ==
nullptr ?
nullptr : std::make_shared<container_type>(*other.values_)),
38 loaded_(other.loaded_)
42 auto operator=(
const RelationCollection& other) -> RelationCollection&
49 auto copiedValues = other.values_ ==
nullptr ? std::shared_ptr<container_type>{} :
50 std::make_shared<container_type>(*other.values_);
51 values_ = std::move(copiedValues);
52 loaded_ = other.loaded_;
56 RelationCollection(RelationCollection&&)
noexcept =
default;
57 auto operator=(RelationCollection&&)
noexcept -> RelationCollection& =
default;
59 explicit RelationCollection(container_type values)
60 : values_(std::make_shared<container_type>(std::move(values))), loaded_(
true)
64 [[nodiscard]]
auto isLoaded()
const noexcept ->
bool
69 auto values() -> container_type&
71 return mutableValues();
74 auto values()
const ->
const container_type&
76 return readableValues();
79 auto begin() -> iterator
81 return values().begin();
84 auto begin()
const -> const_iterator
86 return values().begin();
89 auto cbegin()
const -> const_iterator
91 return values().cbegin();
94 auto end() -> iterator
96 return values().end();
99 auto end()
const -> const_iterator
101 return values().end();
104 auto cend()
const -> const_iterator
106 return values().cend();
109 [[nodiscard]]
auto size()
const noexcept -> size_type
111 return values_ ==
nullptr ? 0 : values_->size();
114 [[nodiscard]]
auto empty()
const noexcept ->
bool
116 return values_ ==
nullptr or values_->empty();
119 auto operator[](size_type index) -> T&
121 return values()[index];
124 auto operator[](size_type index)
const ->
const T&
126 return values()[index];
134 auto setLoaded(container_type values) ->
void
136 values_ = std::make_shared<container_type>(std::move(values));
140 auto mutableValues() -> container_type&
142 if (values_ ==
nullptr)
144 values_ = std::make_shared<container_type>();
150 auto readableValues()
const ->
const container_type&
152 if (values_ ==
nullptr)
154 values_ = std::make_shared<container_type>();
160 mutable std::shared_ptr<container_type> values_;
184 inline static constexpr bool isCollection =
false;
185 inline static constexpr bool isOneToMany =
false;
192 inline static constexpr bool isCollection =
true;
193 inline static constexpr bool isOneToMany =
true;
200 inline static constexpr bool isCollection =
true;
201 inline static constexpr bool isOneToMany =
false;
211 inline static constexpr bool value =
false;
217 inline static constexpr bool value = isRelationCollection<T>;
225inline constexpr bool is_relation_collection_v = detail::isRelationCollection<std::remove_cvref_t<T>>;
228inline constexpr bool is_optional_relation_collection_v = detail::isOptionalRelationCollection<std::remove_cvref_t<T>>;
234inline constexpr bool is_one_to_many_v =
239inline constexpr reflection::FixedString emptyRelationName{
""};
244template <
typename Value,
typename Owner>
247 using OwnerType = Owner;
248 using ValueType = Value;
251template <auto Member>
254template <auto Member>
257template <reflection::FixedString... Names>
260 inline static constexpr std::size_t size =
sizeof...(Names);
261 inline static constexpr std::array<std::string_view,
sizeof...(Names)> values{Names.view()...};
284template <auto Member, auto MappedByMember =
nullptr, reflection::FixedString MappedByName = detail::emptyRelationName>
285 requires std::is_member_object_pointer_v<
decltype(Member)>
288 inline static constexpr auto member = Member;
289 inline static constexpr auto mappedByMember = MappedByMember;
290 inline static constexpr auto mappedByName = MappedByName;
292 template <auto TargetMember>
293 requires std::is_member_object_pointer_v<
decltype(TargetMember)>
294 [[nodiscard]]
consteval auto
297 using collection_t = std::remove_cvref_t<detail::relation_member_value_t<Member>>;
298 using target_t = relation_target_t<collection_t>;
299 static_assert(std::same_as<detail::relation_member_owner_t<TargetMember>, target_t>,
300 "ORM_RELATION_MAPPED_BY_OWNER: mappedBy member must belong to the relation target");
304 template <reflection::FixedString TargetField>
307 static_assert(not TargetField.view().empty(),
308 "ORM_RELATION_MAPPED_BY_EMPTY: mappedBy field name must not be empty");
315template <auto Member, auto MappedByMember, reflection::FixedString MappedByName>
320template <auto Member, auto MappedByMember, reflection::FixedString MappedByName>
329template <
auto Member,
auto MappedByMember =
nullptr, reflection::FixedString MappedByName = detail::emptyRelationName,
330 reflection::FixedString ThroughTable = detail::emptyRelationName,
333 requires std::is_member_object_pointer_v<
decltype(Member)>
336 inline static constexpr auto member = Member;
337 inline static constexpr auto mappedByMember = MappedByMember;
338 inline static constexpr auto mappedByName = MappedByName;
339 inline static constexpr auto throughTable = ThroughTable;
340 using OwnerColumns = OwnerColumnNames;
341 using TargetColumns = TargetColumnNames;
343 template <reflection::FixedString TableName>
344 [[nodiscard]]
consteval auto through()
const
347 static_assert(not TableName.view().empty(),
348 "ORM_RELATION_JUNCTION_EMPTY: junction table name must not be empty");
352 template <auto TargetMember>
353 requires std::is_member_object_pointer_v<
decltype(TargetMember)>
354 [[nodiscard]]
consteval auto
355 mappedBy()
const ->
ManyToManyDescriptor<Member, TargetMember, detail::emptyRelationName, ThroughTable,
356 OwnerColumnNames, TargetColumnNames>
358 using collection_t = std::remove_cvref_t<detail::relation_member_value_t<Member>>;
359 using target_t = relation_target_t<collection_t>;
360 static_assert(std::same_as<detail::relation_member_owner_t<TargetMember>, target_t>,
361 "ORM_RELATION_MAPPED_BY_OWNER: mappedBy member must belong to the relation target");
365 template <reflection::FixedString TargetField>
366 [[nodiscard]]
consteval auto mappedBy()
const
369 static_assert(not TargetField.view().empty(),
370 "ORM_RELATION_MAPPED_BY_EMPTY: mappedBy field name must not be empty");
374 template <reflection::FixedString... Names>
375 [[nodiscard]]
consteval auto
376 ownerColumns()
const ->
ManyToManyDescriptor<Member, MappedByMember, MappedByName, ThroughTable,
379 static_assert(
sizeof...(Names) > 0,
380 "ORM_RELATION_OWNER_COLUMNS_EMPTY: owner junction columns must not be empty");
381 static_assert((not Names.view().empty() && ...),
382 "ORM_RELATION_OWNER_COLUMN_EMPTY: junction column name must not be empty");
386 template <reflection::FixedString... Names>
387 [[nodiscard]]
consteval auto
388 targetColumns()
const ->
ManyToManyDescriptor<Member, MappedByMember, MappedByName, ThroughTable, OwnerColumnNames,
391 static_assert(
sizeof...(Names) > 0,
392 "ORM_RELATION_TARGET_COLUMNS_EMPTY: target junction columns must not be empty");
393 static_assert((not Names.view().empty() && ...),
394 "ORM_RELATION_TARGET_COLUMN_EMPTY: junction column name must not be empty");
401template <
auto Member,
auto MappedByMember, reflection::FixedString MappedByName, reflection::FixedString ThroughTable,
402 typename OwnerColumnNames,
typename TargetColumnNames>
404 ManyToManyDescriptor<Member, MappedByMember, MappedByName, ThroughTable, OwnerColumnNames, TargetColumnNames>>
409template <
auto Member,
auto MappedByMember, reflection::FixedString MappedByName, reflection::FixedString ThroughTable,
410 typename OwnerColumnNames,
typename TargetColumnNames>
412 ManyToManyDescriptor<Member, MappedByMember, MappedByName, ThroughTable, OwnerColumnNames, TargetColumnNames>>
418template <auto Member>
419 requires std::is_member_object_pointer_v<
decltype(Member)>
422 using field_t = std::remove_cvref_t<detail::relation_member_value_t<Member>>;
423 static_assert(is_one_to_many_v<field_t>,
"ORM_RELATION_KIND: oneToMany<Member>() requires an OneToMany<T> member");
427template <auto Member>
428 requires std::is_member_object_pointer_v<
decltype(Member)>
431 using field_t = std::remove_cvref_t<detail::relation_member_value_t<Member>>;
432 static_assert(is_relation_collection_v<field_t> && not is_one_to_many_v<field_t>,
433 "ORM_RELATION_KIND: manyToMany<Member>() requires a ManyToMany<T> member");
437template <
typename... Descriptors>
438[[nodiscard]]
consteval auto relations(Descriptors... descriptors)
441 "ORM_MODEL_RELATIONS_DEFINITION: orm::relations accepts only typed relation descriptors");
442 return std::tuple<Descriptors...>{descriptors...};
A class representing a database in the ORM framework.
Definition database.hpp:67
Database facade bound to one closed compile-time model schema.
Definition database.hpp:704
Definition relations.hpp:174
Definition relations.hpp:167
Definition relations.hpp:26
Typed many-to-many mapping and its compile-time builder.
Definition relations.hpp:335
Typed one-to-many mapping. The descriptor stores no runtime strings: every member and fallback name i...
Definition relations.hpp:287
Definition relations.hpp:276
Definition relations.hpp:271
Definition relations.hpp:266
Definition relations.hpp:210
Definition relations.hpp:183
Definition relations.hpp:259
Definition relations.hpp:242