Lightweight 0.20260625.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::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 a one-to-one relationship. 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, ThroughRecordT, TheOwnerSelector, TheReferencedSelector >
 This API represents a many-to-many relationship between two records through a third record. More...
 
class  Lightweight::HasOneThrough< OtherTable, ThroughTable, 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::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<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 >
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

constexpr std::nullopt_t Lightweight::AutoDetectRelation = std::nullopt
 Selector value meaning "resolve the relationship automatically; the match must be unique".
 
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::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 390 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 23 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 162 of file Description.hpp.

Function Documentation

◆ 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 367 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 167 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 181 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 195 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 209 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 222 of file Description.hpp.

Variable Documentation

◆ 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 117 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 253 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 263 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:302

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 314 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 326 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 354 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 360 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 152 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 269 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 275 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:275

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 351 of file Utils.hpp.