@@ -350,9 +350,17 @@ class DataMapper
350350 template <typename Record>
351351 bool IsModified (Record const & record) const noexcept ;
352352
353- // / Clears the modified state of the record.
354- template <typename Record>
355- void ClearModifiedState (Record& record) noexcept ;
353+ // / Enum to set the modified state of a record.
354+ enum class ModifiedState : uint8_t
355+ {
356+ Modified,
357+ NotModified
358+ };
359+
360+ // / Sets the modified state of the record after receiving from the database.
361+ // / This marks all fields as not modified.
362+ template <ModifiedState state, typename Record>
363+ void SetModifiedState (Record& record) noexcept ;
356364
357365 // / Loads all direct relations to this record.
358366 template <typename Record>
@@ -1323,15 +1331,15 @@ RecordPrimaryKeyType<Record> DataMapper::Create(Record& record)
13231331 if constexpr (FieldType::IsPrimaryKey)
13241332 if constexpr (FieldType::IsAutoAssignPrimaryKey)
13251333 {
1326- if (!record.[:el:].IsModified ())
1334+ using ValueType = typename FieldType::ValueType;
1335+ if constexpr (std::same_as<ValueType, SqlGuid>)
13271336 {
1328- using ValueType = typename FieldType::ValueType;
1329- if constexpr (std::same_as<ValueType, SqlGuid>)
1330- {
1331- if (!record.[:el:].Value ())
1332- record.[:el:] = SqlGuid::Create ();
1333- }
1334- else if constexpr (requires { ValueType {} + 1 ; })
1337+ if (!record.[:el:].Value ())
1338+ record.[:el:] = SqlGuid::Create ();
1339+ }
1340+ else if constexpr (requires { ValueType {} + 1 ; })
1341+ {
1342+ if (record.[:el:].Value () == ValueType {})
13351343 {
13361344 auto maxId = SqlStatement { _connection }.ExecuteDirectScalar <ValueType>(std::format (
13371345 R"sql( SELECT MAX("{}") FROM "{}")sql" , FieldNameOf<el>, RecordTableName<Record>));
@@ -1344,15 +1352,15 @@ RecordPrimaryKeyType<Record> DataMapper::Create(Record& record)
13441352 CallOnPrimaryKey (record, [&]<size_t PrimaryKeyIndex, typename PrimaryKeyType>(PrimaryKeyType& primaryKeyField) {
13451353 if constexpr (PrimaryKeyType::IsAutoAssignPrimaryKey)
13461354 {
1347- if (!primaryKeyField.IsModified ())
1355+ using ValueType = PrimaryKeyType::ValueType;
1356+ if constexpr (std::same_as<ValueType, SqlGuid>)
13481357 {
1349- using ValueType = PrimaryKeyType::ValueType;
1350- if constexpr (std::same_as<ValueType, SqlGuid>)
1351- {
1352- if (!primaryKeyField.Value ())
1353- primaryKeyField = SqlGuid::Create ();
1354- }
1355- else if constexpr (requires { ValueType {} + 1 ; })
1358+ if (!primaryKeyField.Value ())
1359+ primaryKeyField = SqlGuid::Create ();
1360+ }
1361+ else if constexpr (requires { ValueType {} + 1 ; })
1362+ {
1363+ if (primaryKeyField.Value () == ValueType {})
13561364 {
13571365 auto maxId = SqlStatement { _connection }.ExecuteDirectScalar <ValueType>(
13581366 std::format (R"sql( SELECT MAX("{}") FROM "{}")sql" ,
@@ -1370,7 +1378,7 @@ RecordPrimaryKeyType<Record> DataMapper::Create(Record& record)
13701378 if constexpr (HasAutoIncrementPrimaryKey<Record>)
13711379 SetId (record, _stmt.LastInsertId (RecordTableName<Record>));
13721380
1373- ClearModifiedState (record);
1381+ SetModifiedState<ModifiedState::NotModified> (record);
13741382
13751383 if constexpr (QueryOptions.loadRelations )
13761384 ConfigureRelationAutoLoading (record);
@@ -1474,7 +1482,7 @@ void DataMapper::Update(Record& record)
14741482
14751483 _stmt.Execute ();
14761484
1477- ClearModifiedState (record);
1485+ SetModifiedState<ModifiedState::NotModified> (record);
14781486}
14791487
14801488template <typename Record>
@@ -1550,6 +1558,9 @@ std::optional<Record> DataMapper::QuerySingleWithoutRelationAutoLoading(PrimaryK
15501558 if (!detail::ReadSingleResult (_stmt.Connection ().ServerType (), reader, *resultRecord))
15511559 return std::nullopt ;
15521560
1561+ if (resultRecord)
1562+ SetModifiedState<ModifiedState::NotModified>(resultRecord.value ());
1563+
15531564 return resultRecord;
15541565}
15551566
@@ -1558,7 +1569,9 @@ std::optional<Record> DataMapper::QuerySingle(PrimaryKeyTypes&&... primaryKeys)
15581569{
15591570 auto record = QuerySingleWithoutRelationAutoLoading<Record>(std::forward<PrimaryKeyTypes>(primaryKeys)...);
15601571 if (record)
1572+ {
15611573 ConfigureRelationAutoLoading (*record);
1574+ }
15621575 return record;
15631576}
15641577
@@ -1578,6 +1591,10 @@ std::optional<Record> DataMapper::QuerySingle(SqlSelectQueryBuilder selectQuery,
15781591 auto reader = _stmt.GetResultCursor ();
15791592 if (!detail::ReadSingleResult (_stmt.Connection ().ServerType (), reader, *resultRecord))
15801593 return std::nullopt ;
1594+
1595+ if (resultRecord)
1596+ SetModifiedState<ModifiedState::NotModified>(resultRecord.value ());
1597+
15811598 return resultRecord;
15821599}
15831600
@@ -1638,7 +1655,10 @@ std::vector<Record> DataMapper::Query(std::string_view sqlQueryString, InputPara
16381655 result.pop_back ();
16391656
16401657 for (auto & record: result)
1658+ {
1659+ SetModifiedState<ModifiedState::NotModified>(record);
16411660 ConfigureRelationAutoLoading (record);
1661+ }
16421662 }
16431663
16441664 return result;
@@ -1710,16 +1730,16 @@ std::vector<std::tuple<First, Second, Rest...>> DataMapper::Query(SqlSelectQuery
17101730 // Drop the last record, which we failed to fetch (End of result set).
17111731 result.pop_back ();
17121732
1713- if constexpr (QueryOptions. loadRelations )
1733+ for ( auto & record: result )
17141734 {
1715-
1716- for ( auto & record: result)
1717- {
1718- Reflection::template_for< 0 , std::tuple_size_v<value_type>>([&]< auto I>() {
1719- auto & element = std::get<I>(record);
1735+ Reflection::template_for< 0 , std::tuple_size_v<value_type>>([&]< auto I>() {
1736+ auto & element = std::get<I>(record);
1737+ SetModifiedState<ModifiedState::NotModified>(element);
1738+ if constexpr (QueryOptions. loadRelations )
1739+ {
17201740 ConfigureRelationAutoLoading (element);
1721- });
1722- }
1741+ }
1742+ });
17231743 }
17241744
17251745 return result;
@@ -1759,21 +1779,27 @@ std::vector<Record> DataMapper::Query(SqlSelectQueryBuilder::ComposedQuery const
17591779 records.pop_back ();
17601780
17611781 for (auto & record: records)
1782+ {
1783+ SetModifiedState<ModifiedState::NotModified>(record);
17621784 ConfigureRelationAutoLoading (record);
1785+ }
17631786
17641787 return records;
17651788}
17661789
1767- template <typename Record>
1768- void DataMapper::ClearModifiedState (Record& record) noexcept
1790+ template <DataMapper::ModifiedState state, typename Record>
1791+ void DataMapper::SetModifiedState (Record& record) noexcept
17691792{
17701793 static_assert (!std::is_const_v<Record>);
17711794 static_assert (DataMapperRecord<Record>, " Record must satisfy DataMapperRecord" );
17721795
17731796 Reflection::EnumerateMembers (record, []<size_t I, typename FieldType>(FieldType& field) {
17741797 if constexpr (requires { field.SetModified (false ); })
17751798 {
1776- field.SetModified (false );
1799+ if constexpr (state == ModifiedState::Modified)
1800+ field.SetModified (true );
1801+ else
1802+ field.SetModified (false );
17771803 }
17781804 });
17791805}
0 commit comments