Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 8 additions & 78 deletions src/Lightweight/DataMapper/DataMapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,41 +207,6 @@ class DataMapper: public std::enable_shared_from_this<DataMapper>
template <typename Record, typename... InputParameters>
std::vector<Record> Query(SqlSelectQueryBuilder::ComposedQuery const& selectQuery, InputParameters&&... inputParameters);

/// Queries multiple records and returns them as a vector of std::tuple of the given record types.
/// This can be used to query multiple record types in a single query.
///
/// example:
/// @code
/// struct Person
/// {
/// int id;
/// std::string name;
/// std::string email;
/// std::string phone;
/// };
/// struct Address
/// {
/// int id;
/// std::string address;
/// std::string city;
/// std::string country;
/// };
/// void example(DataMapper& dm)
/// {
/// auto const sqlQueryString = R"(SELECT p.*, a.* FROM "Person" p INNER JOIN "Address" a ON p.id = a.id WHERE p.city =
/// Berlin AND a.country = Germany)";
/// auto const records = dm.QueryToTuple<Person, Address>(sqlQueryString);
/// for (auto const& [person, address] : records)
/// {
/// std::println("Person: {}", DataMapper::Inspect(person));
/// std::println("Address: {}", DataMapper::Inspect(address));
/// }
/// }
/// @endcode
template <typename... Records>
requires DataMapperRecords<Records...>
std::vector<std::tuple<Records...>> QueryToTuple(SqlSelectQueryBuilder::ComposedQuery const& selectQuery);

/// Queries multiple records from the database, based on the given query.
///
/// @param sqlQueryString The SQL query string to execute.
Expand Down Expand Up @@ -303,7 +268,7 @@ class DataMapper: public std::enable_shared_from_this<DataMapper>

/// Queries records of different types from the database, based on the given query.
/// User can constructed query that selects columns from the multiple tables
/// this function is uset to get result of the
/// this function is uset to get result of the query
Copy link

Copilot AI Oct 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spelling of 'uset' to 'used'.

Suggested change
/// this function is uset to get result of the query
/// this function is used to get result of the query

Copilot uses AI. Check for mistakes.
///
/// example:
/// @code
Expand All @@ -325,16 +290,13 @@ class DataMapper: public std::enable_shared_from_this<DataMapper>
/// {
/// // do something with elementA and elementC
/// }
template <typename FirstRecord, typename NextRecord, typename... InputParameters>
requires DataMapperRecord<FirstRecord> && DataMapperRecord<NextRecord>
// TODO : need more generic one and we also have queryToTuple
std::vector<std::tuple<FirstRecord, NextRecord>> Query(SqlSelectQueryBuilder::ComposedQuery const& selectQuery,
InputParameters&&... inputParameters);
template <typename First, typename Second, typename... Rest>
requires DataMapperRecords<First> && DataMapperRecords<Second> && DataMapperRecords<Rest...>
Copy link

Copilot AI Oct 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The constraint DataMapperRecords<First> appears incorrect for a single type. Based on the pattern in the codebase where single records use DataMapperRecord (singular) and the removed code used DataMapperRecord<FirstRecord>, this should likely be DataMapperRecord<First> && DataMapperRecord<Second> to match the existing pattern for validating individual record types.

Suggested change
requires DataMapperRecords<First> && DataMapperRecords<Second> && DataMapperRecords<Rest...>
requires DataMapperRecord<First> && DataMapperRecord<Second> && DataMapperRecord<Rest...>

Copilot uses AI. Check for mistakes.
std::vector<std::tuple<First, Second, Rest...>> Query(SqlSelectQueryBuilder::ComposedQuery const& selectQuery);

/// Queries records of different types from the database, based on the given query.
template <typename FirstRecord, typename NextRecord>
requires DataMapperRecord<FirstRecord> && DataMapperRecord<NextRecord>
// TODO : need more generic one and we also have queryToTuple
SqlAllFieldsQueryBuilder<std::tuple<FirstRecord, NextRecord>> Query()
{
std::string fields;
Expand Down Expand Up @@ -1034,11 +996,11 @@ std::vector<Record> DataMapper::Query(std::string_view sqlQueryString, InputPara
return result;
}

template <typename... Records>
requires DataMapperRecords<Records...>
std::vector<std::tuple<Records...>> DataMapper::QueryToTuple(SqlSelectQueryBuilder::ComposedQuery const& selectQuery)
template <typename First, typename Second, typename... Rest>
requires DataMapperRecords<First> && DataMapperRecords<Second> && DataMapperRecords<Rest...>
std::vector<std::tuple<First, Second, Rest...>> DataMapper::Query(SqlSelectQueryBuilder::ComposedQuery const& selectQuery)
{
using value_type = std::tuple<Records...>;
using value_type = std::tuple<First, Second, Rest...>;
auto result = std::vector<value_type> {};

_stmt.Prepare(selectQuery.ToSql());
Expand Down Expand Up @@ -1111,38 +1073,6 @@ std::vector<std::tuple<Records...>> DataMapper::QueryToTuple(SqlSelectQueryBuild
return result;
}

template <typename FirstRecord, typename SecondRecord, typename... InputParameters>
requires DataMapperRecord<FirstRecord> && DataMapperRecord<SecondRecord>
std::vector<std::tuple<FirstRecord, SecondRecord>> DataMapper::Query(SqlSelectQueryBuilder::ComposedQuery const& selectQuery,
InputParameters&&... inputParameters)
{
auto result = std::vector<std::tuple<FirstRecord, SecondRecord>> {};

_stmt.Prepare(selectQuery.ToSql());
_stmt.Execute(std::forward<InputParameters>(inputParameters)...);

auto const ConfigureFetchAndBind = [this](auto& record) {
auto& [recordFirst, recordSecond] = record;
// clang-cl gives false possitive error that *this*
// is not used in the lambda, to avoid the warning,
// use it here explicitly
this->BindOutputColumns<FirstRecord, 1>(recordFirst);
this->BindOutputColumns<SecondRecord, Reflection::CountMembers<FirstRecord> + 1>(recordSecond);
this->ConfigureRelationAutoLoading(recordFirst);
this->ConfigureRelationAutoLoading(recordSecond);
};

ConfigureFetchAndBind(result.emplace_back());
while (_stmt.FetchRow())
ConfigureFetchAndBind(result.emplace_back());

// remove the last empty record
if (!result.empty())
result.pop_back();

return result;
}

template <typename ElementMask, typename Record, typename... InputParameters>
std::vector<Record> DataMapper::Query(SqlSelectQueryBuilder::ComposedQuery const& selectQuery,
InputParameters&&... inputParameters)
Expand Down
2 changes: 1 addition & 1 deletion src/tests/DataMapper/ReadTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -648,7 +648,7 @@ TEST_CASE_METHOD(SqlTestFixture, "GetMultileTypesAsVectorOfTuples", "[DataMapper
SqlAnsiString<20> comment {};
};

auto const records = dm->QueryToTuple<CustomBindingA, CustomBindingB, PartOfC>(query);
auto const records = dm->Query<CustomBindingA, CustomBindingB, PartOfC>(query);
CHECK(!records.empty());

for (auto const& [a, b, c]: records)
Expand Down
Loading