Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compilation fail with sync_schema and inheritance #854

Closed
jahnf opened this issue Nov 26, 2021 · 11 comments
Closed

Compilation fail with sync_schema and inheritance #854

jahnf opened this issue Nov 26, 2021 · 11 comments
Assignees
Labels

Comments

@jahnf
Copy link

jahnf commented Nov 26, 2021

Hey,
I think I found an Issue with inheritance and sync_schema:
With the following code, I get a compilation error:

struct Base {
  std::string name;
  int64_t timestamp;
  int64_t value;
};

struct A : public Base {
  int64_t id;
};

void createdb()
{
  auto storage = sqlite_orm::make_storage("test.db"
    , sqlite_orm::make_table("entries"
        , sqlite_orm::make_column("id", &A::id, sqlite_orm::autoincrement(), sqlite_orm::primary_key())
        , sqlite_orm::make_column("name", &A::name)
        , sqlite_orm::make_column("timestamp", &A::timestamp)
        , sqlite_orm::unique(&A::name, &A::timestamp)
  ));

  for (const auto& res : storage.sync_schema()) {
    (void)res;
    // check sync results here..
  }
}

Error output:

[build]                  from /tmp/test.cc:25:
[build] /third-party/sqlite_orm/sqlite_orm.h: In instantiation of ‘const string* sqlite_orm::internal::storage_impl<H, Ts ...>::column_name(F O::*, typename std::enable_if<(! std::is_same<O, HH>::value)>::type*) const [with O = Base; F = long int; HH = A; H = sqlite_orm::internal::table_t<A, sqlite_orm::internal::column_t<A, long int, const long int& (A::*)() const, void (A::*)(long int), sqlite_orm::internal::autoincrement_t, sqlite_orm::internal::primary_key_t<> >, sqlite_orm::internal::column_t<Base, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >& (Base::*)() const, void (Base::*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)>, sqlite_orm::internal::column_t<Base, long int, const long int& (Base::*)() const, void (Base::*)(long int)>, sqlite_orm::internal::unique_t<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > Base::*, long int Base::*> >; Ts = {}; std::string = std::__cxx11::basic_string<char>; typename std::enable_if<(! std::is_same<O, HH>::value)>::type = void]’:
[build] /third-party/sqlite_orm/sqlite_orm.h:1530:48:   required from ‘const string* sqlite_orm::internal::serializator_context<I>::column_name(F O::*) const [with O = Base; F = long int; I = sqlite_orm::internal::storage_impl<sqlite_orm::internal::table_t<A, sqlite_orm::internal::column_t<A, long int, const long int& (A::*)() const, void (A::*)(long int), sqlite_orm::internal::autoincrement_t, sqlite_orm::internal::primary_key_t<> >, sqlite_orm::internal::column_t<Base, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >& (Base::*)() const, void (Base::*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)>, sqlite_orm::internal::column_t<Base, long int, const long int& (Base::*)() const, void (Base::*)(long int)>, sqlite_orm::internal::unique_t<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > Base::*, long int Base::*> > >; std::string = std::__cxx11::basic_string<char>]’
[build] /third-party/sqlite_orm/sqlite_orm.h:13847:33:   required from ‘sqlite_orm::internal::statement_serializator<sqlite_orm::internal::unique_t<Args ...>, void>::operator()(const statement_type&, const C&) const [with C = sqlite_orm::internal::serializator_context<sqlite_orm::internal::storage_impl<sqlite_orm::internal::table_t<A, sqlite_orm::internal::column_t<A, long int, const long int& (A::*)() const, void (A::*)(long int), sqlite_orm::internal::autoincrement_t, sqlite_orm::internal::primary_key_t<> >, sqlite_orm::internal::column_t<Base, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >& (Base::*)() const, void (Base::*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)>, sqlite_orm::internal::column_t<Base, long int, const long int& (Base::*)() const, void (Base::*)(long int)>, sqlite_orm::internal::unique_t<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > Base::*, long int Base::*> > > >; Args = {std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > Base::*, long int Base::*}; std::string = std::__cxx11::basic_string<char>; sqlite_orm::internal::statement_serializator<sqlite_orm::internal::unique_t<Args ...>, void>::statement_type = sqlite_orm::internal::unique_t<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > Base::*, long int Base::*>]::<lambda(auto:74&)> [with auto:74 = long int Base::* const]’
[build] /third-party/sqlite_orm/sqlite_orm.h:243:27:   required from ‘void sqlite_orm::tuple_helper::iterator_impl<N, Args>::operator()(const std::tuple<_Elements ...>&, const L&, bool) [with L = sqlite_orm::internal::statement_serializator<sqlite_orm::internal::unique_t<Args ...>, void>::operator()(const statement_type&, const C&) const [with C = sqlite_orm::internal::serializator_context<sqlite_orm::internal::storage_impl<sqlite_orm::internal::table_t<A, sqlite_orm::internal::column_t<A, long int, const long int& (A::*)() const, void (A::*)(long int), sqlite_orm::internal::autoincrement_t, sqlite_orm::internal::primary_key_t<> >, sqlite_orm::internal::column_t<Base, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >& (Base::*)() const, void (Base::*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)>, sqlite_orm::internal::column_t<Base, long int, const long int& (Base::*)() const, void (Base::*)(long int)>, sqlite_orm::internal::unique_t<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > Base::*, long int Base::*> > > >; Args = {std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > Base::*, long int Base::*}; std::string = std::__cxx11::basic_string<char>; sqlite_orm::internal::statement_serializator<sqlite_orm::internal::unique_t<Args ...>, void>::statement_type = sqlite_orm::internal::unique_t<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > Base::*, long int Base::*>]::<lambda(auto:74&)>; long unsigned int N = 1; Args = {std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > Base::*, long int Base::*}]’
[build] /third-party/sqlite_orm/sqlite_orm.h:359:91:   required from ‘void sqlite_orm::internal::iterate_tuple(const std::tuple<_Elements ...>&, const L&) [with L = sqlite_orm::internal::statement_serializator<sqlite_orm::internal::unique_t<Args ...>, void>::operator()(const statement_type&, const C&) const [with C = sqlite_orm::internal::serializator_context<sqlite_orm::internal::storage_impl<sqlite_orm::internal::table_t<A, sqlite_orm::internal::column_t<A, long int, const long int& (A::*)() const, void (A::*)(long int), sqlite_orm::internal::autoincrement_t, sqlite_orm::internal::primary_key_t<> >, sqlite_orm::internal::column_t<Base, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >& (Base::*)() const, void (Base::*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)>, sqlite_orm::internal::column_t<Base, long int, const long int& (Base::*)() const, void (Base::*)(long int)>, sqlite_orm::internal::unique_t<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > Base::*, long int Base::*> > > >; Args = {std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > Base::*, long int Base::*}; std::string = std::__cxx11::basic_string<char>; sqlite_orm::internal::statement_serializator<sqlite_orm::internal::unique_t<Args ...>, void>::statement_type = sqlite_orm::internal::unique_t<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > Base::*, long int Base::*>]::<lambda(auto:74&)>; Args = {std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > Base::*, long int Base::*}]’
[build] /third-party/sqlite_orm/sqlite_orm.h:13846:34:   required from ‘std::string sqlite_orm::internal::statement_serializator<sqlite_orm::internal::unique_t<Args ...>, void>::operator()(const statement_type&, const C&) const [with C = sqlite_orm::internal::serializator_context<sqlite_orm::internal::storage_impl<sqlite_orm::internal::table_t<A, sqlite_orm::internal::column_t<A, long int, const long int& (A::*)() const, void (A::*)(long int), sqlite_orm::internal::autoincrement_t, sqlite_orm::internal::primary_key_t<> >, sqlite_orm::internal::column_t<Base, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >& (Base::*)() const, void (Base::*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)>, sqlite_orm::internal::column_t<Base, long int, const long int& (Base::*)() const, void (Base::*)(long int)>, sqlite_orm::internal::unique_t<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > Base::*, long int Base::*> > > >; Args = {std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > Base::*, long int Base::*}; std::string = std::__cxx11::basic_string<char>; sqlite_orm::internal::statement_serializator<sqlite_orm::internal::unique_t<Args ...>, void>::statement_type = sqlite_orm::internal::unique_t<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > Base::*, long int Base::*>]’
[build] /third-party/sqlite_orm/sqlite_orm.h:13116:32:   [ skipping 4 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
[build] /third-party/sqlite_orm/sqlite_orm.h:15141:30:   required from ‘void sqlite_orm::internal::storage_t<Ts>::create_table(sqlite3*, const string&, const I&) [with I = sqlite_orm::internal::storage_impl<sqlite_orm::internal::table_t<A, sqlite_orm::internal::column_t<A, long int, const long int& (A::*)() const, void (A::*)(long int), sqlite_orm::internal::autoincrement_t, sqlite_orm::internal::primary_key_t<> >, sqlite_orm::internal::column_t<Base, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >& (Base::*)() const, void (Base::*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)>, sqlite_orm::internal::column_t<Base, long int, const long int& (Base::*)() const, void (Base::*)(long int)>, sqlite_orm::internal::unique_t<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > Base::*, long int Base::*> > >; Ts = {sqlite_orm::internal::table_t<A, sqlite_orm::internal::column_t<A, long int, const long int& (A::*)() const, void (A::*)(long int), sqlite_orm::internal::autoincrement_t, sqlite_orm::internal::primary_key_t<> >, sqlite_orm::internal::column_t<Base, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >& (Base::*)() const, void (Base::*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)>, sqlite_orm::internal::column_t<Base, long int, const long int& (Base::*)() const, void (Base::*)(long int)>, sqlite_orm::internal::unique_t<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > Base::*, long int Base::*> >}; sqlite3 = sqlite3; std::string = std::__cxx11::basic_string<char>]’
[build] /third-party/sqlite_orm/sqlite_orm.h:15860:25:   required from ‘sqlite_orm::sync_schema_result sqlite_orm::internal::storage_t<Ts>::sync_table(const sqlite_orm::internal::storage_impl<TTable<Cs ...>, Tss ...>&, sqlite3*, bool) [with TTable = sqlite_orm::internal::table_t; Tss = {}; Cs = {A, sqlite_orm::internal::column_t<A, long int, const long int& (A::*)() const, void (A::*)(long int), sqlite_orm::internal::autoincrement_t, sqlite_orm::internal::primary_key_t<> >, sqlite_orm::internal::column_t<Base, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >& (Base::*)() const, void (Base::*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)>, sqlite_orm::internal::column_t<Base, long int, const long int& (Base::*)() const, void (Base::*)(long int)>, sqlite_orm::internal::unique_t<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > Base::*, long int Base::*>}; Ts = {sqlite_orm::internal::table_t<A, sqlite_orm::internal::column_t<A, long int, const long int& (A::*)() const, void (A::*)(long int), sqlite_orm::internal::autoincrement_t, sqlite_orm::internal::primary_key_t<> >, sqlite_orm::internal::column_t<Base, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >& (Base::*)() const, void (Base::*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)>, sqlite_orm::internal::column_t<Base, long int, const long int& (Base::*)() const, void (Base::*)(long int)>, sqlite_orm::internal::unique_t<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > Base::*, long int Base::*> >}; sqlite3 = sqlite3]’
[build] /third-party/sqlite_orm/sqlite_orm.h:15959:26:   required from ‘sqlite_orm::internal::storage_t<Ts>::sync_schema(bool) [with Ts = {sqlite_orm::internal::table_t<A, sqlite_orm::internal::column_t<A, long int, const long int& (A::*)() const, void (A::*)(long int), sqlite_orm::internal::autoincrement_t, sqlite_orm::internal::primary_key_t<> >, sqlite_orm::internal::column_t<Base, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >& (Base::*)() const, void (Base::*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)>, sqlite_orm::internal::column_t<Base, long int, const long int& (Base::*)() const, void (Base::*)(long int)>, sqlite_orm::internal::unique_t<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > Base::*, long int Base::*> >}]::<lambda(auto:102&)> [with auto:102 = sqlite_orm::internal::storage_impl<sqlite_orm::internal::table_t<A, sqlite_orm::internal::column_t<A, long int, const long int& (A::*)() const, void (A::*)(long int), sqlite_orm::internal::autoincrement_t, sqlite_orm::internal::primary_key_t<> >, sqlite_orm::internal::column_t<Base, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >& (Base::*)() const, void (Base::*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)>, sqlite_orm::internal::column_t<Base, long int, const long int& (Base::*)() const, void (Base::*)(long int)>, sqlite_orm::internal::unique_t<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > Base::*, long int Base::*> > >]’
[build] /third-party/sqlite_orm/sqlite_orm.h:9025:18:   required from ‘void sqlite_orm::internal::storage_impl<H, Ts ...>::for_each(const L&) [with L = sqlite_orm::internal::storage_t<Ts>::sync_schema(bool) [with Ts = {sqlite_orm::internal::table_t<A, sqlite_orm::internal::column_t<A, long int, const long int& (A::*)() const, void (A::*)(long int), sqlite_orm::internal::autoincrement_t, sqlite_orm::internal::primary_key_t<> >, sqlite_orm::internal::column_t<Base, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >& (Base::*)() const, void (Base::*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)>, sqlite_orm::internal::column_t<Base, long int, const long int& (Base::*)() const, void (Base::*)(long int)>, sqlite_orm::internal::unique_t<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > Base::*, long int Base::*> >}]::<lambda(auto:102&)>; H = sqlite_orm::internal::table_t<A, sqlite_orm::internal::column_t<A, long int, const long int& (A::*)() const, void (A::*)(long int), sqlite_orm::internal::autoincrement_t, sqlite_orm::internal::primary_key_t<> >, sqlite_orm::internal::column_t<Base, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >& (Base::*)() const, void (Base::*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)>, sqlite_orm::internal::column_t<Base, long int, const long int& (Base::*)() const, void (Base::*)(long int)>, sqlite_orm::internal::unique_t<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > Base::*, long int Base::*> >; Ts = {}]’
[build] /third-party/sqlite_orm/sqlite_orm.h:15958:17:   required from ‘std::map<std::__cxx11::basic_string<char>, sqlite_orm::sync_schema_result> sqlite_orm::internal::storage_t<Ts>::sync_schema(bool) [with Ts = {sqlite_orm::internal::table_t<A, sqlite_orm::internal::column_t<A, long int, const long int& (A::*)() const, void (A::*)(long int), sqlite_orm::internal::autoincrement_t, sqlite_orm::internal::primary_key_t<> >, sqlite_orm::internal::column_t<Base, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >& (Base::*)() const, void (Base::*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)>, sqlite_orm::internal::column_t<Base, long int, const long int& (Base::*)() const, void (Base::*)(long int)>, sqlite_orm::internal::unique_t<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > Base::*, long int Base::*> >}]’
[build] /tmp/test.cc:224:46:   required from here
[build] /third-party/sqlite_orm/sqlite_orm.h:9071:37: error: ‘struct sqlite_orm::internal::storage_impl<>’ has no member named ‘column_name’
[build]  9071 |                 return this->super::column_name(m)
@fnc12
Copy link
Owner

fnc12 commented Nov 28, 2021

try adding explicit type to make_table call:

auto storage = sqlite_orm::make_storage("test.db"
      , sqlite_orm::make_table<Base>("entries"
          , sqlite_orm::make_column("id", &A::id, sqlite_orm::autoincrement(), sqlite_orm::primary_key())
          , sqlite_orm::make_column("name", &A::name)
          , sqlite_orm::make_column("timestamp", &A::timestamp)
          , sqlite_orm::unique(&A::name, &A::timestamp)
    ));

@jahnf
Copy link
Author

jahnf commented Nov 29, 2021

Perfect. Thank you.

@jahnf jahnf closed this as completed Nov 29, 2021
@jahnf
Copy link
Author

jahnf commented Nov 29, 2021

Follow up, with make_table<Base> I cannot insert any As, e.g.

A a{};
storage.insert<A>(a);

How would you achieve that? Or is it best to avoid inheritance with sqlite_orm?

@jahnf jahnf reopened this Nov 29, 2021
@fnc12
Copy link
Owner

fnc12 commented Dec 3, 2021

try storage.insert(a)

@jahnf
Copy link
Author

jahnf commented Dec 6, 2021

try storage.insert(a)

Thanks you for the suggestion but this leads to
third-party/sqlite_orm/sqlite_orm/sqlite_orm.h:15581:79: error: static assertion failed: type is not mapped to a storage

complete code for reference:

  struct Base {
    std::string name;
    int64_t timestamp;
    int64_t value;
  }; 

  struct A : public Base {
    int64_t id;
  };

  auto storage = sqlite_orm::make_storage("test.db"
    , sqlite_orm::make_table<Base>("entries"
          , sqlite_orm::make_column("id", &A::id, sqlite_orm::autoincrement(), sqlite_orm::primary_key())
          , sqlite_orm::make_column("name", &A::name)
          , sqlite_orm::make_column("timestamp", &A::timestamp)
          , sqlite_orm::unique(&A::name, &A::timestamp)
    ));

  for (const auto& res : storage.sync_schema()) {
    (void)res;
    // check sync results here..
  }

  A a;
   storage.insert(a);

@fnc12
Copy link
Owner

fnc12 commented Dec 6, 2021

I need to think here. Probably the first advice was wrong. I'll answer soon

@fnc12 fnc12 added the bug label Dec 6, 2021
@fnc12 fnc12 self-assigned this Dec 6, 2021
@jahnf
Copy link
Author

jahnf commented Dec 6, 2021

I need to think here. Probably the first advice was wrong. I'll answer soon

Alright thank you

For this use case where you might want to reuse existing classes and structs and for storing
them within a database you want to add some fields (e.g. an auto-increment id)

I got the following workaround now:

As described earlier I have a Base class Base:

struct Base {
  std::string name;
  int64_t timestamp;
  int64_t value;
};

I want to store Base objects while adding an additional field, an auto-increment id, without
changing the Base class/struct.

The table should look like this:

  auto storage = sqlite_orm::make_storage("test.db"
    , sqlite_orm::make_table("entries"
      , sqlite_orm::make_column("id", &A::id, sqlite_orm::autoincrement(), sqlite_orm::primary_key())
      , sqlite_orm::make_column("name", &A::name)
      , sqlite_orm::make_column("timestamp", &A::timestamp)
      , sqlite_orm::unique(&A::name, &A::timestamp)
  ));

With the following you will run into all kinds of problems:

struct A : public Base {
   int64_t id = -1;
};

With an additional boilerplate and custom reference_value_wrapper it works:

struct A : public Base {
  int64_t id = -1;

  db::ref_val_wrapper<std::string> name = Base::name;
  db::ref_val_wrapper<int64_t> timestamp = Base::timestamp;
};

The custom ref_val_wrapper and additional definietions for sqlite_orm look like this:

namespace db
{
  template<typename T>
  struct ref_val_wrapper
  {
    ref_val_wrapper(T& t) : refval(static_cast<T*>(&t)) {}
    ref_val_wrapper(T&& t) : refval(std::move(t)) {}

    inline ref_val_wrapper& operator=(T&& t)
    {
      if (std::holds_alternative<T*>(refval)) {
        *std::get<T*>(refval) = std::move(t);
      }
      else {
        std::get<T>(refval) = std::move(t);
      }

      return *this;
    }

    operator const T&() const
    {
      if (std::holds_alternative<T*>(refval))
        return *std::get<T*>(refval);
      else
        return std::get<T>(refval);
    }

    [[nodiscard]]
    inline const T& get() const
    {
      if (std::holds_alternative<T*>(refval))
        return *std::get<T*>(refval);
      else
        return std::get<T>(refval);
    }

    [[nodiscard]]
    inline T& get()
    {
      if (std::holds_alternative<T*>(refval))
        return *std::get<T*>(refval);
      else
        return std::get<T>(refval);
    }

    [[nodiscard]]
    inline bool is_value() const {
      return std::holds_alternative<T>(refval);
    }

    [[nodiscard]]
    inline bool is_reference() const {
      return std::holds_alternative<T*>(refval);
    }

    private:
      std::variant<T*, T> refval;
  };
} // end namespace db

namespace sqlite_orm {
  template<typename T>
  struct type_printer<::db::ref_val_wrapper<T>> : public type_printer<T> {};

  template<typename T>
  struct statement_binder<::db::ref_val_wrapper<T>> {
    int bind(sqlite3_stmt *stmt, int index, const ::db::ref_val_wrapper<T> &valueRef) {
      return statement_binder<T>().bind(stmt, index, valueRef.get());
    }
  };

  template<typename T>
  struct row_extractor<::db::ref_val_wrapper<T>> : public row_extractor<T> {};
} // end namespace sqlite_orm

@fnc12
Copy link
Owner

fnc12 commented Dec 14, 2021

@jahnf fix is here #863. It will be merged after all checks are passed ok

@jahnf
Copy link
Author

jahnf commented Dec 14, 2021

Nice thank you, hopefully I get time tonight to check it out.

@jahnf
Copy link
Author

jahnf commented Dec 14, 2021

👍 works for what I tested - inserting, iterating, iterating with where clauses.

@fnc12
Copy link
Owner

fnc12 commented Dec 14, 2021

@jahnf so you need to use column<A>(&Base::field) instead when you use inheritance. Is that ok?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants