Skip to content

How to update nullable value in a table with an auto incrementing primary key? #108

@PatrickMiller728

Description

@PatrickMiller728

I have a table defined as:

struct Example {
  sqlgen::PrimaryKey<int, sqlgen::auto_incr> id;
  std::optional<int> nullable;
}

I need to be able to update nullable to either an integer or null value. I attempted to use sqlgen::update as follows:

const auto conn = sqlgen::sqlite::connect();
const auto newNullable = std::optional{3};
const auto id = 1;

using namespace sqlgen;
using namespace sqlgen::literals;

write<Example>(conn, {.nullable = 2});

const auto query = update<Example>("nullable"_c.set(newNullable)) | where("id"_c == id);
query(conn).value();

And get a compilation error:

D:\C++\sqlgen-test\build\debug-msvc\vcpkg_installed\x64-windows\include\sqlgen\transpilation\to_value.hpp(39): error C2338: static_assert failed: 'Unsupported type'
D:\C++\sqlgen-test\build\debug-msvc\vcpkg_installed\x64-windows\include\sqlgen\transpilation\to_value.hpp(39): note: the template instantiation context (the oldest one first) is
D:\C++\sqlgen-test\main.cpp(18): note: see reference to function template instantiation 'rfl::Result<rfl::Ref<sqlgen::sqlite::Connection>> sqlgen::Update<ValueType,SetsType,ConditionType>::()<rfl::Result<rfl::Ref<sqlgen::sqlite::Connection>>>(const _T0 &) const' being compiled
        with
        [
            ValueType=Example,
            SetsType=sqlgen::update::TupleType,
            ConditionType=sqlgen::transpilation::Condition<sqlgen::transpilation::conditions::Equal<sqlgen::transpilation::Col<rfl::internal::StringLiteral<3>{std::array<char,3>{char105,100,0}},rfl::internal::StringLiteral<1>{std::array<char,1>{char0}}>,sqlgen::transpilation::Value<int>>>,
            _T0=rfl::Result<rfl::Ref<sqlgen::sqlite::Connection>>
        ]
D:\C++\sqlgen-test\build\debug-msvc\vcpkg_installed\x64-windows\include\sqlgen\transpilation\../update.hpp(40): note: see reference to function template instantiation 'rfl::Result<rfl::Ref<sqlgen::sqlite::Connection>> sqlgen::update_impl<ValueType,SetsType,ConditionType,sqlgen::sqlite::Connection>(const rfl::Result<rfl::Ref<sqlgen::sqlite::Connection>> &,const SetsType &,const WhereType &)' being compiled
        with
        [
            ValueType=Example,
            SetsType=sqlgen::update::TupleType,
            ConditionType=sqlgen::transpilation::Condition<sqlgen::transpilation::conditions::Equal<sqlgen::transpilation::Col<rfl::internal::StringLiteral<3>{std::array<char,3>{char105,100,0}},rfl::internal::StringLiteral<1>{std::array<char,1>{char0}}>,sqlgen::transpilation::Value<int>>>,
            WhereType=sqlgen::transpilation::Condition<sqlgen::transpilation::conditions::Equal<sqlgen::transpilation::Col<rfl::internal::StringLiteral<3>{std::array<char,3>{char105,100,0}},rfl::internal::StringLiteral<1>{std::array<char,1>{char0}}>,sqlgen::transpilation::Value<int>>>
        ]
D:\C++\sqlgen-test\build\debug-msvc\vcpkg_installed\x64-windows\include\sqlgen\transpilation\../update.hpp(32): note: see reference to function template instantiation 'rfl::Result<rfl::Ref<sqlgen::sqlite::Connection>>::and_then::Result_U rfl::Result<rfl::Ref<sqlgen::sqlite::Connection>>::and_then<sqlgen::update_impl::<lambda_1>>(const F &) const &' being compiled
        with
        [
            F=sqlgen::update_impl::<lambda_1>
        ]
D:\C++\sqlgen-test\build\debug-msvc\vcpkg_installed\x64-windows\include\rfl\Result.hpp(144): note: see reference to class template instantiation 'std::invoke_result<sqlgen::update_impl::<lambda_1>,rfl::Ref<sqlgen::sqlite::Connection>>' being compiled
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.43.34808\include\type_traits(1815): note: see reference to alias template instantiation 'std::_Decltype_invoke_nonzero<_Callable,rfl::Ref<sqlgen::sqlite::Connection>,>' being compiled
        with
        [
            _Callable=sqlgen::update_impl::<lambda_1>
        ]
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.43.34808\include\type_traits(1811): note: while compiling class template member function 'unknown-type std::_Invoker_functor::_Call(_Callable &&,_Types ...) noexcept(<expr>)'
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.43.34808\include\type_traits(1602): note: see reference to function template instantiation 'rfl::Result<rfl::Ref<sqlgen::sqlite::Connection>> sqlgen::update_impl::<lambda_1>::operator ()<rfl::Ref<sqlgen::sqlite::Connection>>(const _T5 &) const' being compiled
        with
        [
            _T5=rfl::Ref<sqlgen::sqlite::Connection>
        ]
D:\C++\sqlgen-test\build\debug-msvc\vcpkg_installed\x64-windows\include\sqlgen\transpilation\../update.hpp(33): note: see reference to function template instantiation 'rfl::Result<rfl::Ref<sqlgen::sqlite::Connection>> sqlgen::update_impl<ValueType,SetsType,ConditionType,sqlgen::sqlite::Connection>(const rfl::Ref<sqlgen::sqlite::Connection> &,const SetsType &,const WhereType &)' being compiled
        with
        [
            ValueType=Example,
            SetsType=sqlgen::update::TupleType,
            ConditionType=sqlgen::transpilation::Condition<sqlgen::transpilation::conditions::Equal<sqlgen::transpilation::Col<rfl::internal::StringLiteral<3>{std::array<char,3>{char105,100,0}},rfl::internal::StringLiteral<1>{std::array<char,1>{char0}}>,sqlgen::transpilation::Value<int>>>,
            WhereType=sqlgen::transpilation::Condition<sqlgen::transpilation::conditions::Equal<sqlgen::transpilation::Col<rfl::internal::StringLiteral<3>{std::array<char,3>{char105,100,0}},rfl::internal::StringLiteral<1>{std::array<char,1>{char0}}>,sqlgen::transpilation::Value<int>>>
        ]
D:\C++\sqlgen-test\build\debug-msvc\vcpkg_installed\x64-windows\include\sqlgen\transpilation\../update.hpp(21): note: see reference to function template instantiation 'sqlgen::dynamic::Update sqlgen::transpilation::to_update<ValueType,SetsType,ConditionType>(const SetsType &,const WhereType &)' being compiled
        with
        [
            ValueType=Example,
            SetsType=sqlgen::update::TupleType,
            ConditionType=sqlgen::transpilation::Condition<sqlgen::transpilation::conditions::Equal<sqlgen::transpilation::Col<rfl::internal::StringLiteral<3>{std::array<char,3>{char105,100,0}},rfl::internal::StringLiteral<1>{std::array<char,1>{char0}}>,sqlgen::transpilation::Value<int>>>,
            WhereType=sqlgen::transpilation::Condition<sqlgen::transpilation::conditions::Equal<sqlgen::transpilation::Col<rfl::internal::StringLiteral<3>{std::array<char,3>{char105,100,0}},rfl::internal::StringLiteral<1>{std::array<char,1>{char0}}>,sqlgen::transpilation::Value<int>>>
        ]
D:\C++\sqlgen-test\build\debug-msvc\vcpkg_installed\x64-windows\include\sqlgen\transpilation/to_update.hpp(26): note: see reference to function template instantiation 'std::vector<sqlgen::dynamic::Update::Set,std::allocator<sqlgen::dynamic::Update::Set>> sqlgen::transpilation::to_sets<ValueType,SetsType>(const SetsType &)' being compiled
        with
        [
            ValueType=Example,
            SetsType=sqlgen::update::TupleType
        ]
D:\C++\sqlgen-test\build\debug-msvc\vcpkg_installed\x64-windows\include\sqlgen\transpilation\to_sets.hpp(75): note: see reference to function template instantiation 'std::vector<sqlgen::dynamic::Update::Set,std::allocator<sqlgen::dynamic::Update::Set>> rfl::apply<sqlgen::transpilation::to_sets::<lambda_1>,sqlgen::transpilation::Set<sqlgen::transpilation::Col<rfl::internal::StringLiteral<9>{std::array<char,9>{_Ty110,117,108,108,97,98,108,101,0}},rfl::internal::StringLiteral<1>{std::array<_Ty,1>{_Ty0}}>,std::optional<int>>>(F &&,const rfl::Tuple<sqlgen::transpilation::Set<sqlgen::transpilation::Col<rfl::internal::StringLiteral<9>{std::array<_Ty,9>{_Ty110,117,108,108,97,98,108,101,0}},rfl::internal::StringLiteral<1>{std::array<_Ty,1>{_Ty0}}>,std::optional<int>>> &)' being compiled
        with
        [
            _Ty=char,
            F=sqlgen::transpilation::to_sets::<lambda_1>
        ]
D:\C++\sqlgen-test\build\debug-msvc\vcpkg_installed\x64-windows\include\rfl\apply.hpp(13): note: see reference to function template instantiation 'std::vector<sqlgen::dynamic::Update::Set,std::allocator<sqlgen::dynamic::Update::Set>> rfl::internal::tuple::apply<F&,sqlgen::transpilation::Set<sqlgen::transpilation::Col<rfl::internal::StringLiteral<9>{std::array<char,9>{_Ty110,117,108,108,97,98,108,101,0}},rfl::internal::StringLiteral<1>{std::array<_Ty,1>{_Ty0}}>,std::optional<int>>,0>(sqlgen::transpilation::to_sets::<lambda_1>&,const rfl::Tuple<sqlgen::transpilation::Set<sqlgen::transpilation::Col<rfl::internal::StringLiteral<9>{std::array<_Ty,9>{_Ty110,117,108,108,97,98,108,101,0}},rfl::internal::StringLiteral<1>{std::array<_Ty,1>{_Ty0}}>,std::optional<int>>> &,std::integer_sequence<int,0>)' being compiled
        with
        [
            F=sqlgen::transpilation::to_sets::<lambda_1>,
            _Ty=char
        ]
D:\C++\sqlgen-test\build\debug-msvc\vcpkg_installed\x64-windows\include\rfl\internal/tuple/apply.hpp(13): note: see reference to function template instantiation 'std::vector<sqlgen::dynamic::Update::Set,std::allocator<sqlgen::dynamic::Update::Set>> sqlgen::transpilation::to_sets::<lambda_1>::operator ()<rfl::Tuple<sqlgen::transpilation::Set<sqlgen::transpilation::Col<rfl::internal::StringLiteral<9>{std::array<char,9>{_Ty110,117,108,108,97,98,108,101,0}},rfl::internal::StringLiteral<1>{std::array<_Ty,1>{_Ty0}}>,std::optional<int>>>::get::Type>(const rfl::Tuple<sqlgen::transpilation::Set<sqlgen::transpilation::Col<rfl::internal::StringLiteral<9>{std::array<_Ty,9>{_Ty110,117,108,108,97,98,108,101,0}},rfl::internal::StringLiteral<1>{std::array<_Ty,1>{_Ty0}}>,std::optional<int>>>::get::Type &) const' being compiled
        with
        [
            _Ty=char
        ]
D:\C++\sqlgen-test\build\debug-msvc\vcpkg_installed\x64-windows\include\sqlgen\transpilation\to_sets.hpp(77): note: see reference to function template instantiation 'sqlgen::dynamic::Update::Set sqlgen::transpilation::to_set<ValueType,rfl::Tuple<sqlgen::transpilation::Set<sqlgen::transpilation::Col<rfl::internal::StringLiteral<9>{std::array<char,9>{_Ty110,117,108,108,97,98,108,101,0}},rfl::internal::StringLiteral<1>{std::array<_Ty,1>{_Ty0}}>,std::optional<int>>>::get::Type>(const SetType &)' being compiled
        with
        [
            ValueType=Example,
            _Ty=char,
            SetType=rfl::Tuple<sqlgen::transpilation::Set<sqlgen::transpilation::Col<rfl::internal::StringLiteral<9>{std::array<char,9>{char110,117,108,108,97,98,108,101,0}},rfl::internal::StringLiteral<1>{std::array<char,1>{char0}}>,std::optional<int>>>::get::Type
        ]
D:\C++\sqlgen-test\build\debug-msvc\vcpkg_installed\x64-windows\include\sqlgen\transpilation\to_sets.hpp(70): note: see reference to function template instantiation 'sqlgen::dynamic::Update::Set sqlgen::transpilation::ToSet<Example,sqlgen::transpilation::Set<sqlgen::transpilation::Col<rfl::internal::StringLiteral<9>{std::array<char,9>{_Ty110,117,108,108,97,98,108,101,0}},rfl::internal::StringLiteral<1>{std::array<_Ty,1>{_Ty0}}>,std::optional<int>>>::()<SetType>(const _T0 &) const' being compiled
        with
        [
            _Ty=char,
            SetType=rfl::Tuple<sqlgen::transpilation::Set<sqlgen::transpilation::Col<rfl::internal::StringLiteral<9>{std::array<char,9>{char110,117,108,108,97,98,108,101,0}},rfl::internal::StringLiteral<1>{std::array<char,1>{char0}}>,std::optional<int>>>::get::Type,
            _T0=rfl::Tuple<sqlgen::transpilation::Set<sqlgen::transpilation::Col<rfl::internal::StringLiteral<9>{std::array<char,9>{char110,117,108,108,97,98,108,101,0}},rfl::internal::StringLiteral<1>{std::array<char,1>{char0}}>,std::optional<int>>>::get::Type
        ]
D:\C++\sqlgen-test\build\debug-msvc\vcpkg_installed\x64-windows\include\sqlgen\transpilation\to_sets.hpp(40): note: see reference to function template instantiation 'sqlgen::dynamic::Value sqlgen::transpilation::to_value<T>(const T &)' being compiled
        with
        [
            T=std::optional<int>
        ]
D:\C++\sqlgen-test\build\debug-msvc\vcpkg_installed\x64-windows\include\sqlgen\transpilation\to_value.hpp(46): note: see reference to class template instantiation 'sqlgen::transpilation::ToValue<std::optional<int>>' being compiled
D:\C++\sqlgen-test\build\debug-msvc\vcpkg_installed\x64-windows\include\sqlgen\transpilation\to_value.hpp(18): note: while compiling class template member function 'sqlgen::dynamic::Value sqlgen::transpilation::ToValue<std::optional<int>>::operator ()(const T &) const'
        with
        [
            T=std::optional<int>
        ]
D:\C++\sqlgen-test\build\debug-msvc\vcpkg_installed\x64-windows\include\sqlgen\transpilation\to_value.hpp(46): note: see the first reference to 'sqlgen::transpilation::ToValue<std::optional<int>>::operator ()' in 'sqlgen::transpilation::to_value'
D:\C++\sqlgen-test\build\debug-msvc\vcpkg_installed\x64-windows\include\sqlgen\transpilation\to_sets.hpp(40): note: see the first reference to 'sqlgen::transpilation::to_value' in 'sqlgen::transpilation::ToSet<Example,sqlgen::transpilation::Set<sqlgen::transpilation::Col<rfl::internal::StringLiteral<9>{std::array<char,9>{_Ty110,117,108,108,97,98,108,101,0}},rfl::internal::StringLiteral<1>{std::array<_Ty,1>{_Ty0}}>,std::optional<int>>>::()'
        with
        [
            _Ty=char
        ]
D:\C++\sqlgen-test\build\debug-msvc\vcpkg_installed\x64-windows\include\sqlgen\transpilation\to_sets.hpp(70): note: see the first reference to 'sqlgen::transpilation::ToSet<Example,sqlgen::transpilation::Set<sqlgen::transpilation::Col<rfl::internal::StringLiteral<9>{std::array<char,9>{_Ty110,117,108,108,97,98,108,101,0}},rfl::internal::StringLiteral<1>{std::array<_Ty,1>{_Ty0}}>,std::optional<int>>>::()' in 'sqlgen::transpilation::to_set'
        with
        [
            _Ty=char
        ]
D:\C++\sqlgen-test\build\debug-msvc\vcpkg_installed\x64-windows\include\sqlgen\transpilation\to_sets.hpp(77): note: see the first reference to 'sqlgen::transpilation::to_set' in 'sqlgen::transpilation::to_sets::<lambda_1>::operator ()'
D:\C++\sqlgen-test\build\debug-msvc\vcpkg_installed\x64-windows\include\rfl\internal/tuple/apply.hpp(13): note: see the first reference to 'sqlgen::transpilation::to_sets::<lambda_1>::operator ()' in 'rfl::internal::tuple::apply'
D:\C++\sqlgen-test\build\debug-msvc\vcpkg_installed\x64-windows\include\rfl\apply.hpp(13): note: see the first reference to 'rfl::internal::tuple::apply' in 'rfl::apply'
D:\C++\sqlgen-test\build\debug-msvc\vcpkg_installed\x64-windows\include\sqlgen\transpilation\to_sets.hpp(75): note: see the first reference to 'rfl::apply' in 'sqlgen::transpilation::to_sets'
D:\C++\sqlgen-test\build\debug-msvc\vcpkg_installed\x64-windows\include\sqlgen\transpilation/to_update.hpp(26): note: see the first reference to 'sqlgen::transpilation::to_sets' in 'sqlgen::transpilation::to_update'
D:\C++\sqlgen-test\build\debug-msvc\vcpkg_installed\x64-windows\include\sqlgen\transpilation\../update.hpp(21): note: see the first reference to 'sqlgen::transpilation::to_update' in 'sqlgen::update_impl'
D:\C++\sqlgen-test\build\debug-msvc\vcpkg_installed\x64-windows\include\sqlgen\transpilation\../update.hpp(33): note: see the first reference to 'sqlgen::update_impl' in 'sqlgen::update_impl::<lambda_1>::operator ()'
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.43.34808\include\type_traits(1602): note: see the first reference to 'sqlgen::update_impl::<lambda_1>::operator ()' in 'std::_Invoker_functor::_Call'

Which led me to try to use sqlgen::insert_or_replace:

const auto query = sqlgen::insert_or_replace<Example>({.id = id, .nullable = newNullable});
const auto result = query(conn);
if (!result) {
    const auto& err = result.error();
    std::cerr << err.what() << "\n";
}

Which outputs:

Preparing the following statement failed: INSERT INTO "Example" ("nullable") VALUES (?) ON CONFLICT () DO UPDATE SET nullable=excluded.nullable; Reason: near ")": syntax error

What is the recommended way to update this table? Or do I need to change my approach?
Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions