Lightweight 0.20260921.0
Loading...
Searching...
No Matches
Data Mapper

The data mapper is a high level API for mapping records to and from the database using high level C++ syntax. More...

Concepts

concept  Lightweight::ConnectionType
 Satisfied by Connection specializations.
 
concept  Lightweight::DataMapperRecord
 Represents a record type that can be used with the DataMapper.
 
concept  Lightweight::RelationSelector
 Constrains what may be used to single out one of several foreign keys into the same table.
 
concept  Lightweight::FieldWithStorage
 
concept  Lightweight::RecordColumnMember
 Requires that T maps onto a column of its record's table.
 
concept  Lightweight::HasDescription
 Satisfied when a Description specialization exists for the given record type.
 

Classes

class  Lightweight::BelongsTo< TheReferencedField, ColumnNameOverrideString, Nullable >
 Represents the many-to-one side of a foreign-key relationship. More...
 
struct  Lightweight::Connection< FromPtr, IntoPtr >
 One column pair of a composite foreign key: "this record's column references that one". More...
 
class  Lightweight::CompositeForeignKey< Connections >
 Represents a foreign key spanning several columns. More...
 
class  Lightweight::DataMapper
 Main API for mapping records to and from the database using high level C++ syntax. More...
 
class  Lightweight::SqlRequireLoadedError
 Represents an error when a record is required to be loaded but is not. More...
 
struct  Lightweight::Field< T, P1, P2 >
 Represents a single column in a table. More...
 
class  Lightweight::HasMany< OtherRecord, TheInverseSelector >
 This HasMany<OtherRecord> represents a simple one-to-many relationship between two records. More...
 
class  Lightweight::HasManyThrough< ReferencedRecordT, ThroughSpec, TheOwnerSelector, TheReferencedSelector >
 This API represents a many-to-many relationship between two records through a third record. More...
 
class  Lightweight::HasOneThrough< OtherTable, ThroughSpec, TheOwnerSelector, TheThroughSelector >
 Represents a one-to-one relationship through a join table. More...
 
class  Lightweight::SqlCoreDataMapperQueryBuilder< Record, Derived, QueryOptions >
 
class  Lightweight::SqlAllFieldsQueryBuilder< Record, QueryOptions, Execution >
 Represents a query builder that retrieves all fields of a record. More...
 
struct  Lightweight::Through< JoinRecordT >
 Marks the join record of a relationship that is reached through an intermediate table. More...
 
struct  Lightweight::RecordMemberList< MemberPointers >
 Compile-time list of a record's members, stored as pointers-to-member. More...
 
struct  Lightweight::Description< Record >
 Customization point providing pre-computed reflection metadata for a record type. More...
 

Typedefs

template<auto Field>
using Lightweight::ReferencedFieldTypeOf = std::remove_cvref_t< decltype(std::declval< MemberClassType< decltype(Field)> >().*Field)>::ValueType
 Retrieves the type of a member field in a record.
 
template<size_t... Ints>
using Lightweight::SqlElements = std::integer_sequence< size_t, Ints... >
 Represents a sequence of indexes that can be used alongside Query() to retrieve only part of the record.
 
template<typename ThroughSpec >
using Lightweight::ThroughRecordOf = typename detail::ThroughRecordOfHelper< ThroughSpec >::type
 Resolves the join record of a through-relationship from its template argument.
 
template<typename Record >
using Lightweight::RecordPrimaryKeyTuple = typename detail::RecordPrimaryKeyTupleHelper< Record >::type
 The tuple of a record's primary key value types, in member declaration order.
 
template<std::size_t I, typename Record >
using Lightweight::RecordMemberTypeOf = detail::RecordMemberTypeOfDispatch< I, std::remove_cvref_t< Record >, HasDescription< Record > >::type
 Type of the member at index I — from the descriptor if present, else via reflection.
 

Functions

template<typename Record >
RecordPrimaryKeyTuple< Record > Lightweight::GetPrimaryKeyFields (Record const &record)
 Reads every primary key value of record, in member declaration order.
 
template<typename Record >
LIGHTWEIGHT_FORCE_INLINE RecordPrimaryKeyType< Record > Lightweight::GetPrimaryKeyField (Record const &record) noexcept
 
template<std::size_t I, typename Record >
constexpr decltype(auto) Lightweight::GetRecordMemberAt (Record &&record)
 Returns a reference to the member at index I — from the descriptor if present, else via reflection.
 
template<typename Record , typename Callable >
constexpr void Lightweight::EnumerateRecordMembers (Record &record, Callable &&callable)
 Invokes callable as callable<I>(member) for each member of record.
 
template<typename ElementMask , typename Record , typename Callable >
constexpr void Lightweight::EnumerateRecordMembers (Record &record, Callable &&callable)
 Invokes callable as callable<I>(member) for each member selected by ElementMask.
 
template<typename Record , typename Callable >
constexpr void Lightweight::EnumerateRecordMembers (Callable &&callable)
 Invokes callable as callable<I, MemberType>() for each member of Record.
 
template<typename Record , typename Callable , typename ResultType >
constexpr ResultType Lightweight::FoldRecordMembers (ResultType initialValue, Callable const &callable)
 Folds over a record's members as result = callable<I, MemberType>(result).
 

Variables

template<typename T >
constexpr bool Lightweight::IsCompositeForeignKey = detail::IsCompositeForeignKeyType<std::remove_cvref_t<T>>::value
 Whether T is a CompositeForeignKey.
 
constexpr std::nullopt_t Lightweight::AutoDetectRelation = std::nullopt
 Selector value meaning "resolve the relationship automatically; the match must be unique".
 
template<typename T >
constexpr bool Lightweight::IsThrough = detail::IsThroughType<std::remove_cvref_t<T>>::value
 
template<typename OwnerRecord , typename ChildRecord , auto Selector = AutoDetectRelation>
constexpr size_t Lightweight::InverseBelongsToIndexOf = detail::InverseBelongsToResolver<OwnerRecord, ChildRecord, Selector>::Index
 Member index, within ChildRecord, of the BelongsTo member that points back to OwnerRecord.
 
template<typename OwnerRecord , typename ChildRecord , auto Selector = AutoDetectRelation>
constexpr std::string_view Lightweight::InverseBelongsToFieldNameOf
 SQL column name of the foreign key that links ChildRecord back to OwnerRecord.
 
template<typename Record >
constexpr size_t Lightweight::RecordColumnCount
 Represents the number of members of a record that map onto a column of a result set.
 
template<typename Record >
constexpr size_t Lightweight::RecordStorageFieldCount
 
template<typename T >
constexpr bool Lightweight::HasPrimaryKey = detail::CheckFieldProperty<[]<typename Field>() { return IsPrimaryKey<Field>; }, T>
 Tests if the given record type does contain a primary key.
 
template<typename T >
constexpr bool Lightweight::HasAutoIncrementPrimaryKey
 Tests if the given record type does contain an auto increment primary key.
 
template<typename Record >
constexpr std::size_t Lightweight::RecordPrimaryKeyCount = std::tuple_size_v<RecordPrimaryKeyTuple<Record>>
 Number of members of Record marked as a primary key.
 
template<typename Record >
constexpr bool Lightweight::HasCompositePrimaryKey = RecordPrimaryKeyCount<Record> > 1
 Whether Record's identity spans more than one column.
 
template<typename Record >
constexpr std::size_t Lightweight::RecordMemberCount
 Number of members in a record — from the descriptor if present, else via reflection.
 
template<std::size_t I, typename Record >
constexpr std::string_view Lightweight::FieldNameAt = detail::FieldNameAt<I, Record>()
 Returns the SQL field name of the given field index in the record.
 
template<typename Record >
constexpr std::string_view Lightweight::RecordTableName = detail::RecordTableNameImpl<Record>::Value
 Holds the SQL tabl ename for the given record type.
 
template<auto ReferencedField>
constexpr auto Lightweight::FullyQualifiedNameOf
 Holds the fully qualified column reference (table + column) for the given field.
 

Detailed Description

The data mapper is a high level API for mapping records to and from the database using high level C++ syntax.

Typedef Documentation

◆ ReferencedFieldTypeOf

template<auto Field>
using Lightweight::ReferencedFieldTypeOf = typedef std::remove_cvref_t<decltype(std::declval<MemberClassType<decltype(Field)> >().*Field)>::ValueType

Retrieves the type of a member field in a record.

Field must be a member of the record type, and it must be a field type, e.g. Field<int> or BelongsTo<OtherRecord>.

using MyRecord = Record {
Field<int> value;
Field<std::optional<char>> optionalValue;
};
using MyFieldType = ReferencedFieldTypeOf<&MyRecord::value>; // Retrieves `int`
using MyOptionalFieldType = ReferencedFieldTypeOf<&MyRecord::optionalValue>; // Retrieves `std::optional<char>`
Represents a single column in a table.
Definition Field.hpp:84

Definition at line 392 of file Field.hpp.

◆ SqlElements

template<size_t... Ints>
using Lightweight::SqlElements = typedef std::integer_sequence<size_t, Ints...>

Represents a sequence of indexes that can be used alongside Query() to retrieve only part of the record.

Definition at line 25 of file Record.hpp.

◆ ThroughRecordOf

template<typename ThroughSpec >
using Lightweight::ThroughRecordOf = typedef typename detail::ThroughRecordOfHelper<ThroughSpec>::type

Resolves the join record of a through-relationship from its template argument.

Accepts both the Through<T> marker and the deprecated bare T spelling, yielding T either way.

Template Parameters
ThroughSpecEither Through<T> or, deprecated, T.
See also
Through

Definition at line 231 of file Record.hpp.

◆ RecordPrimaryKeyTuple

template<typename Record >
using Lightweight::RecordPrimaryKeyTuple = typedef typename detail::RecordPrimaryKeyTupleHelper<Record>::type

The tuple of a record's primary key value types, in member declaration order.

Unlike RecordPrimaryKeyType, which names a single field's type, this covers composite keys: for a record with several members marked PrimaryKey it is a tuple of all of them. For a single-key record it is a one-element tuple.

Added alongside the single-key helpers rather than replacing them, so no existing caller changes behaviour; only composite-aware code reaches for this.

Definition at line 540 of file Record.hpp.

◆ RecordMemberTypeOf

template<std::size_t I, typename Record >
using Lightweight::RecordMemberTypeOf = typedef detail::RecordMemberTypeOfDispatch<I, std::remove_cvref_t<Record>, HasDescription<Record> >::type

Type of the member at index I — from the descriptor if present, else via reflection.

Definition at line 169 of file Description.hpp.

Function Documentation

◆ GetPrimaryKeyFields()

template<typename Record >
RecordPrimaryKeyTuple< Record > Lightweight::GetPrimaryKeyFields ( Record const &  record)

Reads every primary key value of record, in member declaration order.

This is the order a primary key lookup binds its arguments in, so the returned tuple can be applied straight to QuerySingle/Update/Delete.

Parameters
recordRecord to read.
Returns
The key values as a tuple.

Definition at line 566 of file Record.hpp.

◆ GetPrimaryKeyField()

template<typename Record >
LIGHTWEIGHT_FORCE_INLINE RecordPrimaryKeyType< Record > Lightweight::GetPrimaryKeyField ( Record const &  record)
inlinenoexcept

Returns the first primary key field of the record.

Definition at line 592 of file Record.hpp.

References Lightweight::EnumerateRecordMembers().

Referenced by Lightweight::DataMapper::ConfigureRelationAutoLoading(), and Lightweight::DataMapper::Create().

◆ GetRecordMemberAt()

template<std::size_t I, typename Record >
constexpr decltype(auto) Lightweight::GetRecordMemberAt ( Record &&  record)
constexpr

Returns a reference to the member at index I — from the descriptor if present, else via reflection.

Definition at line 174 of file Description.hpp.

◆ EnumerateRecordMembers() [1/3]

template<typename Record , typename Callable >
constexpr void Lightweight::EnumerateRecordMembers ( Record &  record,
Callable &&  callable 
)
constexpr

Invokes callable as callable<I>(member) for each member of record.

Mirrors Reflection::EnumerateMembers(object, callable) but reads the descriptor when present, avoiding the aggregate-decomposition (ToTuple) instantiation.

Definition at line 188 of file Description.hpp.

Referenced by Lightweight::DataMapper::ConfigureRelationAutoLoading(), Lightweight::DataMapper::Delete(), Lightweight::GetPrimaryKeyField(), Lightweight::DataMapper::LoadRelations(), Lightweight::DataMapper::SetId(), Lightweight::DataMapper::SetModifiedState(), and Lightweight::DataMapper::Update().

◆ EnumerateRecordMembers() [2/3]

template<typename ElementMask , typename Record , typename Callable >
constexpr void Lightweight::EnumerateRecordMembers ( Record &  record,
Callable &&  callable 
)
constexpr

Invokes callable as callable<I>(member) for each member selected by ElementMask.

Mirrors Reflection::EnumerateMembers<ElementMask>(object, callable) (partial-column queries) but reads the descriptor when present. ElementMask is a std::integer_sequence<std::size_t, ...>.

Definition at line 202 of file Description.hpp.

◆ EnumerateRecordMembers() [3/3]

template<typename Record , typename Callable >
constexpr void Lightweight::EnumerateRecordMembers ( Callable &&  callable)
constexpr

Invokes callable as callable<I, MemberType>() for each member of Record.

Mirrors Reflection::EnumerateMembers<Object>(callable) but reads the descriptor when present.

Definition at line 216 of file Description.hpp.

◆ FoldRecordMembers()

template<typename Record , typename Callable , typename ResultType >
constexpr ResultType Lightweight::FoldRecordMembers ( ResultType  initialValue,
Callable const &  callable 
)
constexpr

Folds over a record's members as result = callable<I, MemberType>(result).

Mirrors Reflection::FoldMembers<Object>(initialValue, callable) but reads the descriptor when present.

Definition at line 229 of file Description.hpp.

Variable Documentation

◆ IsCompositeForeignKey

template<typename T >
constexpr bool Lightweight::IsCompositeForeignKey = detail::IsCompositeForeignKeyType<std::remove_cvref_t<T>>::value
constexpr

Whether T is a CompositeForeignKey.

Definition at line 461 of file CompositeForeignKey.hpp.

◆ AutoDetectRelation

constexpr std::nullopt_t Lightweight::AutoDetectRelation = std::nullopt
inlineconstexpr

Selector value meaning "resolve the relationship automatically; the match must be unique".

This is the default for every relationship selector. Pass a SqlRealName instead to name the foreign key column explicitly, which is required when a record holds more than one foreign key into the same table.

Definition at line 119 of file Record.hpp.

◆ IsThrough

template<typename T >
constexpr bool Lightweight::IsThrough = detail::IsThroughType<std::remove_cvref_t<T>>::value
constexpr

Tests whether T is a Through marker.

Definition at line 181 of file Record.hpp.

◆ InverseBelongsToIndexOf

template<typename OwnerRecord , typename ChildRecord , auto Selector = AutoDetectRelation>
constexpr size_t Lightweight::InverseBelongsToIndexOf = detail::InverseBelongsToResolver<OwnerRecord, ChildRecord, Selector>::Index
constexpr

Member index, within ChildRecord, of the BelongsTo member that points back to OwnerRecord.

This is how HasMany, HasManyThrough and HasOneThrough locate their foreign key column: by matching the relationship type, never by member position. Using it is a hard compile-time error when ChildRecord declares no such BelongsTo, or when it declares more than one and Selector does not single out exactly one of them.

Template Parameters
OwnerRecordThe record being referenced (the "one" side of the relationship).
ChildRecordThe record holding the foreign key (the "many" side).
SelectorSingles out one of several foreign keys, see the RelationSelector concept.

Definition at line 351 of file Record.hpp.

◆ InverseBelongsToFieldNameOf

template<typename OwnerRecord , typename ChildRecord , auto Selector = AutoDetectRelation>
constexpr std::string_view Lightweight::InverseBelongsToFieldNameOf
constexpr
Initial value:
=
FieldNameAt<InverseBelongsToIndexOf<OwnerRecord, ChildRecord, Selector>, ChildRecord>

SQL column name of the foreign key that links ChildRecord back to OwnerRecord.

Template Parameters
OwnerRecordThe record being referenced (the "one" side of the relationship).
ChildRecordThe record holding the foreign key (the "many" side).
SelectorSingles out one of several foreign keys, see the RelationSelector concept.

Definition at line 361 of file Record.hpp.

◆ RecordColumnCount

template<typename Record >
constexpr size_t Lightweight::RecordColumnCount
constexpr
Initial value:
=
FoldRecordMembers<Record>(size_t { 0 }, []<size_t I, typename Field>(size_t const accum) constexpr {
return accum + 1;
else
return accum;
})
Requires that T maps onto a column of its record's table.
Definition Record.hpp:400

Represents the number of members of a record that map onto a column of a result set.

This is the width the record occupies in a projection built from the RecordColumnMember concept (e.g. SqlSelectQueryBuilder::Fields), and therefore the amount by which the index must be advanced to reach the first column of the record that follows it in a multi-record projection. It differs from RecordMemberCount exactly by the number of relation members (HasMany, HasManyThrough, HasOneThrough, ...), which have no column of their own.

Definition at line 412 of file Record.hpp.

◆ RecordStorageFieldCount

template<typename Record >
constexpr size_t Lightweight::RecordStorageFieldCount
constexpr
Initial value:
=
FoldRecordMembers<Record>(size_t { 0 }, []<size_t I, typename Field>(size_t const accum) constexpr {
if constexpr (FieldWithStorage<Field>)
return accum + 1;
else
return accum;
})

Represents the number of fields with storage in a record.

Definition at line 424 of file Record.hpp.

◆ HasPrimaryKey

template<typename T >
constexpr bool Lightweight::HasPrimaryKey = detail::CheckFieldProperty<[]<typename Field>() { return IsPrimaryKey<Field>; }, T>
constexpr

Tests if the given record type does contain a primary key.

Definition at line 452 of file Record.hpp.

◆ HasAutoIncrementPrimaryKey

template<typename T >
constexpr bool Lightweight::HasAutoIncrementPrimaryKey
constexpr
Initial value:
=
detail::CheckFieldProperty<[]<typename Field>() { return IsAutoIncrementPrimaryKey<Field>; }, T>

Tests if the given record type does contain an auto increment primary key.

Definition at line 458 of file Record.hpp.

◆ RecordPrimaryKeyCount

template<typename Record >
constexpr std::size_t Lightweight::RecordPrimaryKeyCount = std::tuple_size_v<RecordPrimaryKeyTuple<Record>>
constexpr

Number of members of Record marked as a primary key.

One for an ordinary record, more for a composite key, zero for a keyless record.

Definition at line 548 of file Record.hpp.

◆ HasCompositePrimaryKey

template<typename Record >
constexpr bool Lightweight::HasCompositePrimaryKey = RecordPrimaryKeyCount<Record> > 1
constexpr

Whether Record's identity spans more than one column.

Definition at line 554 of file Record.hpp.

◆ RecordMemberCount

template<typename Record >
constexpr std::size_t Lightweight::RecordMemberCount
constexpr
Initial value:
= []() constexpr {
if constexpr (HasDescription<Record>)
return Description<std::remove_cvref_t<Record>>::FieldCount;
else
return Reflection::CountMembers<Record>;
}()
Satisfied when a Description specialization exists for the given record type.

Number of members in a record — from the descriptor if present, else via reflection.

Definition at line 159 of file Description.hpp.

◆ FieldNameAt

template<std::size_t I, typename Record >
constexpr std::string_view Lightweight::FieldNameAt = detail::FieldNameAt<I, Record>()
inlineconstexpr

Returns the SQL field name of the given field index in the record.

Definition at line 268 of file Utils.hpp.

◆ RecordTableName

template<typename Record >
constexpr std::string_view Lightweight::RecordTableName = detail::RecordTableNameImpl<Record>::Value
constexpr

Holds the SQL tabl ename for the given record type.

Definition at line 274 of file Utils.hpp.

Referenced by Lightweight::SqlWhereClauseBuilder< Derived >::InnerJoin().

◆ FullyQualifiedNameOf

template<auto ReferencedField>
constexpr auto Lightweight::FullyQualifiedNameOf
inlineconstexpr
Initial value:
= SqlQualifiedTableColumnName {
.tableName = RecordTableName<MemberClassType<decltype(ReferencedField)>>,
.columnName = FieldNameOf<ReferencedField>,
}
constexpr std::string_view RecordTableName
Holds the SQL tabl ename for the given record type.
Definition Utils.hpp:274

Holds the fully qualified column reference (table + column) for the given field.

Template Parameters
ReferencedFieldA pointer-to-member identifying the field.
constexpr auto ref = FullyQualifiedNameOf<&Person::id>;
static_assert(ref.tableName == "Person");
static_assert(ref.columnName == "id");

The result is an SqlQualifiedTableColumnName accepted by every column-name entry point in the builder (Field, Fields, Where, OrderBy, GroupBy, Aggregate::*, joins). The builder applies the quoting.

Definition at line 350 of file Utils.hpp.