-
Notifications
You must be signed in to change notification settings - Fork 15
Open
Description
I am looking into migrating to sqlpp23. I found one issue.
I am using a lot of strong types. Mapping enum fields in the database to enum fields in C++, strong typed id's, so that mistakes like: tableA_id == tableB_id cannot happen. Well, a small reproducible example says more then words:
#include <sqlpp23/mock_db/mock_db.h>
#include <sqlpp23/sqlpp23.h>
#include <sqlpp23/tests/core/make_test_connection.h>
// Strong type
struct TestId {
int64_t value{0};
explicit TestId(int64_t v) : value(v) {}
TestId() = default;
bool operator==(const TestId&) const = default;
};
// Table definition
struct Test_ {
struct Id {
SQLPP_CREATE_NAME_TAG_FOR_SQL_AND_CPP(id, id);
using data_type = TestId; // <-- strong type as data_type
using has_default = std::false_type;
};
struct Symbol {
SQLPP_CREATE_NAME_TAG_FOR_SQL_AND_CPP(symbol, symbol);
using data_type = ::sqlpp::text;
using has_default = std::false_type;
};
SQLPP_CREATE_NAME_TAG_FOR_SQL_AND_CPP(stock, stock);
template<typename T>
using _table_columns = sqlpp::table_columns<T, Id, Symbol>;
using _required_insert_columns = sqlpp::detail::type_set<
sqlpp::column_t<sqlpp::table_t<Test_>, Id>,
sqlpp::column_t<sqlpp::table_t<Test_>, Symbol>>;
};
using Test = ::sqlpp::table_t<Test_>;
// Glue needed for sqlpp
template <>
struct sqlpp::data_type_of<TestId> {
using type = sqlpp::integral;
};
template <typename Context>
auto to_sql_string(Context& ctx, const TestId& id) {
return to_sql_string(ctx, id.value);
}
template <>
struct sqlpp::result_data_type_of<TestId> {
using type = TestId; // result row will hold a TestId directly
};
// End glue
int main() {
auto db = sqlpp::mock_db::make_test_connection({});
const Test stock;
for (const auto& row : db(select(all_of(stock)).from(stock))) {
TestId id = row.id;
(void)id;
}
return 0;
}Compiling with: clang++ -std=c++23 -I include -I tests/include test.cpp gave the following output:
In file included from test.cpp:1:
In file included from include/sqlpp23/mock_db/mock_db.h:30:
In file included from include/sqlpp23/mock_db/database/connection.h:32:
include/sqlpp23/core/query/result_row.h:55:12: error: no matching member function for call to
'read_field'
55 | target.read_field(index, _field::operator()());
| ~~~~~~~^~~~~~~~~~
include/sqlpp23/core/query/result_row.h:72:36: note: in instantiation of function template
specialization 'sqlpp::detail::result_field<0, sqlpp::field_spec_t<Test_::Id::_sqlpp_name_tag,
TestId>>::_read_field<sqlpp::mock_db::text_result_t>' requested here
72 | (result_field<Is, FieldSpecs>::_read_field(target), ...);
| ^
include/sqlpp23/core/query/result_row.h:134:12: note: in instantiation of function template
specialization 'sqlpp::detail::result_row_impl<std::integer_sequence<unsigned long, 0, 1>,
sqlpp::field_spec_t<Test_::Id::_sqlpp_name_tag, TestId>, sqlpp::field_spec_t<Test_::Symbol::_sqlpp_name_tag,
sqlpp::text>>::_read_fields<sqlpp::mock_db::text_result_t>' requested here
134 | _impl::_read_fields(target);
| ^
include/sqlpp23/core/query/result_row.h:151:9: note: in instantiation of function template
specialization 'sqlpp::result_row_t<sqlpp::field_spec_t<Test_::Id::_sqlpp_name_tag, TestId>,
sqlpp::field_spec_t<Test_::Symbol::_sqlpp_name_tag, sqlpp::text>>::_read_fields<sqlpp::mock_db::text_result_t>'
requested here
151 | row._read_fields(target);
| ^
include/sqlpp23/mock_db/text_result.h:92:42: note: in instantiation of function template specialization
'sqlpp::detail::result_row_bridge::read_fields<sqlpp::field_spec_t<Test_::Id::_sqlpp_name_tag, TestId>,
sqlpp::field_spec_t<Test_::Symbol::_sqlpp_name_tag, sqlpp::text>, sqlpp::mock_db::text_result_t>' requested here
92 | sqlpp::detail::result_row_bridge{}.read_fields(result_row, *this);
| ^
include/sqlpp23/core/result.h:70:13: note: in instantiation of function template specialization
'sqlpp::mock_db::text_result_t::next<sqlpp::result_row_t<sqlpp::field_spec_t<Test_::Id::_sqlpp_name_tag, TestId>,
sqlpp::field_spec_t<Test_::Symbol::_sqlpp_name_tag, sqlpp::text>>>' requested here
70 | _result.next(_result_row);
| ^
include/sqlpp23/core/clause/select_column_list.h:166:12: note: in instantiation of member function
'sqlpp::result_t<sqlpp::mock_db::text_result_t, sqlpp::result_row_t<sqlpp::field_spec_t<Test_::Id::_sqlpp_name_tag,
TestId>, sqlpp::field_spec_t<Test_::Symbol::_sqlpp_name_tag, sqlpp::text>>>::result_t' requested here
166 | return {statement_handler_t{}.select(std::forward<Statement>(self), db)};
| ^
include/sqlpp23/core/query/statement_handler.h:38:47: note: in instantiation of function template
specialization 'sqlpp::select_result_methods_t<sqlpp::column_t<sqlpp::table_t<Test_>, Test_::Id>,
sqlpp::column_t<sqlpp::table_t<Test_>, Test_::Symbol>>::_run<const sqlpp::statement_t<sqlpp::select_t,
sqlpp::select_column_list_t<std::tuple<>, std::tuple<sqlpp::column_t<sqlpp::table_t<Test_>, Test_::Id>,
sqlpp::column_t<sqlpp::table_t<Test_>, Test_::Symbol>>>, sqlpp::from_t<sqlpp::table_t<Test_>>, sqlpp::no_where_t,
sqlpp::no_group_by_t, sqlpp::no_having_t, sqlpp::no_order_by_t, sqlpp::no_limit_t, sqlpp::no_offset_t,
sqlpp::no_union_t, sqlpp::no_for_update_t> &, sqlpp::mock_db::connection_base>' requested here
38 | return std::forward<Statement>(statement)._run(db);
| ^
include/sqlpp23/mock_db/text_result.h:106:8: note: candidate function not viable: no known conversion
from 'TestId' to 'bool &' for 2nd argument
106 | void read_field(size_t index, bool& value) {
| ^ ~~~~~~~~~~~
include/sqlpp23/mock_db/text_result.h:111:8: note: candidate function not viable: no known conversion
from 'TestId' to 'double &' for 2nd argument
111 | void read_field(size_t index, double& value) {
| ^ ~~~~~~~~~~~~~
include/sqlpp23/mock_db/text_result.h:115:8: note: candidate function not viable: no known conversion
from 'TestId' to 'int64_t &' (aka 'long &') for 2nd argument
115 | void read_field(size_t index, int64_t& value) {
| ^ ~~~~~~~~~~~~~~
include/sqlpp23/mock_db/text_result.h:119:8: note: candidate function not viable: no known conversion
from 'TestId' to 'uint64_t &' (aka 'unsigned long &') for 2nd argument
119 | void read_field(size_t index, uint64_t& value) {
| ^ ~~~~~~~~~~~~~~~
include/sqlpp23/mock_db/text_result.h:123:8: note: candidate function not viable: no known conversion
from 'TestId' to 'std::span<const uint8_t> &' (aka 'span<const unsigned char> &') for 2nd argument
123 | void read_field(size_t index, std::span<const uint8_t>& value) {
| ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/sqlpp23/mock_db/text_result.h:129:8: note: candidate function not viable: no known conversion
from 'TestId' to 'std::string_view &' (aka 'basic_string_view<char> &') for 2nd argument
129 | void read_field(size_t index, std::string_view& value) {
| ^ ~~~~~~~~~~~~~~~~~~~~~~~
include/sqlpp23/mock_db/text_result.h:134:8: note: candidate function not viable: no known conversion
from 'TestId' to 'std::chrono::sys_days &' (aka 'time_point<std::chrono::system_clock, duration<long, ratio<86400>>>
&') for 2nd argument
134 | void read_field(size_t index, std::chrono::sys_days& value) {
| ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/sqlpp23/mock_db/text_result.h:162:8: note: candidate function not viable: no known conversion
from 'TestId' to '::sqlpp::chrono::sys_microseconds &' (aka 'time_point<std::chrono::system_clock, duration<long,
ratio<1, 1000000>>> &') for 2nd argument
162 | void read_field(size_t index, ::sqlpp::chrono::sys_microseconds& value) {
| ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/sqlpp23/mock_db/text_result.h:190:8: note: candidate function not viable: no known conversion
from 'TestId' to '::std::chrono::microseconds &' (aka 'duration<long, ratio<1, 1000000>> &') for 2nd argument
190 | void read_field(size_t index, ::std::chrono::microseconds& value) {
| ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/sqlpp23/mock_db/text_result.h:219:8: note: candidate template ignored: could not match
'std::optional<T>' against 'TestId'
219 | auto read_field(size_t index, std::optional<T>& value) -> void {
| ^
1 error generated.As you can see in the example, I am implementing the to_sql_string function, I expected something like a from_sql_string to do the other way around.
With sqlpp11 I had implementation of different data_types which handled exactly this. Hopefully this functionality can be implemented in sqlpp23!
Thank you for the wonderful library!
Regards, Matthijs
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels