Skip to content
This repository has been archived by the owner on Jan 3, 2024. It is now read-only.

Commit

Permalink
Properly checked everywhere for availability of 'upsert clause' feature
Browse files Browse the repository at this point in the history
  • Loading branch information
trueqbit committed Mar 10, 2023
1 parent e41c35a commit ccca01c
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 72 deletions.
12 changes: 9 additions & 3 deletions dev/ast/upsert_clause.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#pragma once

#include <tuple> // std::tuple, std::make_tuple
#include <type_traits> // std::false_type, std::true_type
#if SQLITE_VERSION_NUMBER >= 3024000
#include <tuple> // std::tuple
#include <utility> // std::forward, std::move
#endif

#include "../functional/cxx_type_traits_polyfill.h"

Expand All @@ -24,7 +25,7 @@ namespace sqlite_orm {

template<class... ActionsArgs>
upsert_clause<args_tuple, std::tuple<ActionsArgs...>> do_update(ActionsArgs... actions) {
return {std::move(this->args), {std::make_tuple(std::forward<ActionsArgs>(actions)...)}};
return {std::move(this->args), {std::forward<ActionsArgs>(actions)...}};
}
};

Expand All @@ -40,8 +41,13 @@ namespace sqlite_orm {

template<class T>
using is_upsert_clause = polyfill::is_specialization_of<T, upsert_clause>;
#else
template<class T>
struct is_upsert_clause : polyfill::bool_constant<false> {};
#endif
}

#if SQLITE_VERSION_NUMBER >= 3024000
/**
* ON CONFLICT upsert clause builder function.
* @example
Expand Down
6 changes: 3 additions & 3 deletions dev/ast_iterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,9 @@ namespace sqlite_orm {
}
};

template<class... TargetArgs, class... ActionsArgs>
struct ast_iterator<upsert_clause<std::tuple<TargetArgs...>, std::tuple<ActionsArgs...>>, void> {
using node_type = upsert_clause<std::tuple<TargetArgs...>, std::tuple<ActionsArgs...>>;
template<class T>
struct ast_iterator<T, match_if<is_upsert_clause, T>> {
using node_type = T;

template<class L>
void operator()(const node_type& expression, L& lambda) const {
Expand Down
5 changes: 2 additions & 3 deletions dev/node_tuple.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,8 @@ namespace sqlite_orm {
using type = tuple_cat_t<args_tuple, expression_tuple>;
};

template<class... TargetArgs, class... ActionsArgs>
struct node_tuple<upsert_clause<std::tuple<TargetArgs...>, std::tuple<ActionsArgs...>>, void>
: node_tuple<std::tuple<ActionsArgs...>> {};
template<class T>
struct node_tuple<T, match_if<is_upsert_clause, T>> : node_tuple<typename T::actions_tuple> {};

template<class... Args>
struct node_tuple<set_t<Args...>, void> {
Expand Down
6 changes: 3 additions & 3 deletions dev/statement_serializer.h
Original file line number Diff line number Diff line change
Expand Up @@ -224,9 +224,9 @@ namespace sqlite_orm {
}
};

template<class... TargetArgs, class... ActionsArgs>
struct statement_serializer<upsert_clause<std::tuple<TargetArgs...>, std::tuple<ActionsArgs...>>, void> {
using statement_type = upsert_clause<std::tuple<TargetArgs...>, std::tuple<ActionsArgs...>>;
template<class T>
struct statement_serializer<T, match_if<is_upsert_clause, T>> {
using statement_type = T;

template<class Ctx>
std::string operator()(const statement_type& statement, const Ctx& context) const {
Expand Down
125 changes: 65 additions & 60 deletions include/sqlite_orm/sqlite_orm.h
Original file line number Diff line number Diff line change
Expand Up @@ -11325,9 +11325,10 @@ namespace sqlite_orm {

// #include "ast/upsert_clause.h"

#include <tuple> // std::tuple, std::make_tuple
#include <type_traits> // std::false_type, std::true_type
#if SQLITE_VERSION_NUMBER >= 3024000
#include <tuple> // std::tuple
#include <utility> // std::forward, std::move
#endif

// #include "../functional/cxx_type_traits_polyfill.h"

Expand All @@ -11349,7 +11350,7 @@ namespace sqlite_orm {

template<class... ActionsArgs>
upsert_clause<args_tuple, std::tuple<ActionsArgs...>> do_update(ActionsArgs... actions) {
return {std::move(this->args), {std::make_tuple(std::forward<ActionsArgs>(actions)...)}};
return {std::move(this->args), {std::forward<ActionsArgs>(actions)...}};
}
};

Expand All @@ -11365,8 +11366,13 @@ namespace sqlite_orm {

template<class T>
using is_upsert_clause = polyfill::is_specialization_of<T, upsert_clause>;
#else
template<class T>
struct is_upsert_clause : polyfill::bool_constant<false> {};
#endif
}

#if SQLITE_VERSION_NUMBER >= 3024000
/**
* ON CONFLICT upsert clause builder function.
* @example
Expand Down Expand Up @@ -12485,9 +12491,9 @@ namespace sqlite_orm {
}
};

template<class... TargetArgs, class... ActionsArgs>
struct ast_iterator<upsert_clause<std::tuple<TargetArgs...>, std::tuple<ActionsArgs...>>, void> {
using node_type = upsert_clause<std::tuple<TargetArgs...>, std::tuple<ActionsArgs...>>;
template<class T>
struct ast_iterator<T, match_if<is_upsert_clause, T>> {
using node_type = T;

template<class L>
void operator()(const node_type& expression, L& lambda) const {
Expand Down Expand Up @@ -14313,13 +14319,13 @@ namespace sqlite_orm {
(this->extract(values[Idx], std::get<Idx>(tuple)), ...);
}
#else
template<class Tpl, size_t I, size_t... Idx>
void operator()(sqlite3_value** values, Tpl& tuple, std::index_sequence<I, Idx...>) const {
this->extract(values[I], std::get<I>(tuple));
(*this)(values, tuple, std::index_sequence<Idx...>{});
}
template<class Tpl, size_t... Idx>
void operator()(sqlite3_value** /*values*/, Tpl&, std::index_sequence<Idx...>) const {}
template<class Tpl, size_t I, size_t... Idx>
void operator()(sqlite3_value** values, Tpl& tuple, std::index_sequence<I, Idx...>) const {
this->extract(values[I], std::get<I>(tuple));
(*this)(values, tuple, std::index_sequence<Idx...>{});
}
template<class Tpl, size_t... Idx>
void operator()(sqlite3_value** /*values*/, Tpl&, std::index_sequence<Idx...>) const {}
#endif
template<class T>
void extract(sqlite3_value* value, T& t) const {
Expand Down Expand Up @@ -15695,9 +15701,9 @@ namespace sqlite_orm {
}
};

template<class... TargetArgs, class... ActionsArgs>
struct statement_serializer<upsert_clause<std::tuple<TargetArgs...>, std::tuple<ActionsArgs...>>, void> {
using statement_type = upsert_clause<std::tuple<TargetArgs...>, std::tuple<ActionsArgs...>>;
template<class T>
struct statement_serializer<T, match_if<is_upsert_clause, T>> {
using statement_type = T;

template<class Ctx>
std::string operator()(const statement_type& statement, const Ctx& context) const {
Expand Down Expand Up @@ -18375,7 +18381,7 @@ namespace sqlite_orm {
#if SQLITE_VERSION_NUMBER >= 3035000 // DROP COLUMN feature exists (v3.35.0)
res = sync_schema_result::old_columns_removed;
#else
gottaCreateTable = true;
gottaCreateTable = true;
#endif
} else {
res = sync_schema_result::old_columns_removed;
Expand Down Expand Up @@ -18693,13 +18699,13 @@ namespace sqlite_orm {
std::ref(processObject),
std::ref(expression.transformer));
#else
auto& transformer = expression.transformer;
std::for_each(expression.range.first,
expression.range.second,
[&processObject, &transformer](auto& item) {
const object_type& object = polyfill::invoke(transformer, item);
processObject(object);
});
auto& transformer = expression.transformer;
std::for_each(expression.range.first,
expression.range.second,
[&processObject, &transformer](auto& item) {
const object_type& object = polyfill::invoke(transformer, item);
processObject(object);
});
#endif
},
[&processObject](auto& expression) {
Expand Down Expand Up @@ -18739,13 +18745,13 @@ namespace sqlite_orm {
std::ref(processObject),
std::ref(expression.transformer));
#else
auto& transformer = expression.transformer;
std::for_each(expression.range.first,
expression.range.second,
[&processObject, &transformer](auto& item) {
const object_type& object = polyfill::invoke(transformer, item);
processObject(object);
});
auto& transformer = expression.transformer;
std::for_each(expression.range.first,
expression.range.second,
[&processObject, &transformer](auto& item) {
const object_type& object = polyfill::invoke(transformer, item);
processObject(object);
});
#endif
},
[&processObject](auto& expression) {
Expand Down Expand Up @@ -18837,22 +18843,22 @@ namespace sqlite_orm {
}
return std::move(res).value();
#else
auto& table = this->get_table<T>();
auto stepRes = sqlite3_step(stmt);
switch(stepRes) {
case SQLITE_ROW: {
T res;
object_from_column_builder<T> builder{res, stmt};
table.for_each_column(builder);
return res;
} break;
case SQLITE_DONE: {
throw std::system_error{orm_error_code::not_found};
} break;
default: {
throw_translated_sqlite_error(stmt);
}
auto& table = this->get_table<T>();
auto stepRes = sqlite3_step(stmt);
switch(stepRes) {
case SQLITE_ROW: {
T res;
object_from_column_builder<T> builder{res, stmt};
table.for_each_column(builder);
return res;
} break;
case SQLITE_DONE: {
throw std::system_error{orm_error_code::not_found};
} break;
default: {
throw_translated_sqlite_error(stmt);
}
}
#endif
}

Expand Down Expand Up @@ -19036,9 +19042,8 @@ namespace sqlite_orm {
using type = tuple_cat_t<args_tuple, expression_tuple>;
};

template<class... TargetArgs, class... ActionsArgs>
struct node_tuple<upsert_clause<std::tuple<TargetArgs...>, std::tuple<ActionsArgs...>>, void>
: node_tuple<std::tuple<ActionsArgs...>> {};
template<class T>
struct node_tuple<T, match_if<is_upsert_clause, T>> : node_tuple<typename T::actions_tuple> {};

template<class... Args>
struct node_tuple<set_t<Args...>, void> {
Expand Down Expand Up @@ -19679,9 +19684,9 @@ namespace sqlite_orm {
#if __cpp_lib_ranges >= 201911L
auto it = std::ranges::find(res, columnName, &table_xinfo::name);
#else
auto it = std::find_if(res.begin(), res.end(), [&columnName](const table_xinfo& ti) {
return ti.name == columnName;
});
auto it = std::find_if(res.begin(), res.end(), [&columnName](const table_xinfo& ti) {
return ti.name == columnName;
});
#endif
if(it != res.end()) {
it->pk = static_cast<int>(i + 1);
Expand Down Expand Up @@ -19754,9 +19759,9 @@ namespace sqlite_orm {
}
res = sync_schema_result::old_columns_removed;
#else
// extra table columns than storage columns
this->backup_table(db, table, {});
res = sync_schema_result::old_columns_removed;
// extra table columns than storage columns
this->backup_table(db, table, {});
res = sync_schema_result::old_columns_removed;
#endif
}

Expand Down Expand Up @@ -19820,11 +19825,11 @@ namespace sqlite_orm {
#if __cpp_lib_ranges >= 201911L
auto columnToIgnoreIt = std::ranges::find(columnsToIgnore, columnName, &table_xinfo::name);
#else
auto columnToIgnoreIt = std::find_if(columnsToIgnore.begin(),
columnsToIgnore.end(),
[&columnName](const table_xinfo* tableInfo) {
return columnName == tableInfo->name;
});
auto columnToIgnoreIt = std::find_if(columnsToIgnore.begin(),
columnsToIgnore.end(),
[&columnName](const table_xinfo* tableInfo) {
return columnName == tableInfo->name;
});
#endif
if(columnToIgnoreIt == columnsToIgnore.end()) {
columnNames.push_back(cref(columnName));
Expand Down
2 changes: 2 additions & 0 deletions tests/ast_iterator_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,12 +207,14 @@ TEST_CASE("ast_iterator") {
expected.push_back(typeid(&User::id));
iterate_ast(node, lambda);
}
#if SQLITE_VERSION_NUMBER >= 3024000
SECTION("upsert_clause") {
auto node = on_conflict(&User::id).do_update(set(c(&User::name) = excluded(&User::name)));
expected.push_back(typeid(&User::name));
expected.push_back(typeid(&User::name));
iterate_ast(node, lambda);
}
#endif
SECTION("into") {
auto node = into<User>();
iterate_ast(node, lambda);
Expand Down
2 changes: 2 additions & 0 deletions tests/statement_serializer_tests/ast/upsert_clause.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using namespace sqlite_orm;

#if SQLITE_VERSION_NUMBER >= 3024000
TEST_CASE("upsert_clause") {
using internal::serialize;
struct Vocabulary {
Expand Down Expand Up @@ -102,3 +103,4 @@ TEST_CASE("upsert_clause") {
}
REQUIRE(value == expected);
}
#endif
2 changes: 2 additions & 0 deletions tests/static_tests/node_tuple.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -925,13 +925,15 @@ TEST_CASE("Node tuple") {
using ExpectedTuple = tuple<decltype(&User::id)>;
STATIC_REQUIRE(std::is_same<Tuple, ExpectedTuple>::value);
}
#if SQLITE_VERSION_NUMBER >= 3024000
SECTION("upsert_clause") {
auto statement = on_conflict(&User::id).do_update(set(c(&User::name) = excluded(&User::name)));
using Statement = decltype(statement);
using Tuple = node_tuple_t<Statement>;
using ExpectedTuple = tuple<decltype(&User::name), decltype(&User::name)>;
STATIC_REQUIRE(std::is_same<Tuple, ExpectedTuple>::value);
}
#endif
SECTION("group_by") {
auto statement = group_by(&User::id);
using Statement = decltype(statement);
Expand Down

0 comments on commit ccca01c

Please sign in to comment.