diff options
Diffstat (limited to 'include/boost/sqlite/detail')
-rw-r--r-- | include/boost/sqlite/detail/aggregate_function.hpp | 166 | ||||
-rw-r--r-- | include/boost/sqlite/detail/catch.hpp | 169 | ||||
-rw-r--r-- | include/boost/sqlite/detail/config.hpp | 83 | ||||
-rw-r--r-- | include/boost/sqlite/detail/exception.hpp | 48 | ||||
-rw-r--r-- | include/boost/sqlite/detail/scalar_function.hpp | 172 | ||||
-rw-r--r-- | include/boost/sqlite/detail/vtable.hpp | 611 | ||||
-rw-r--r-- | include/boost/sqlite/detail/window_function.hpp | 238 |
7 files changed, 0 insertions, 1487 deletions
diff --git a/include/boost/sqlite/detail/aggregate_function.hpp b/include/boost/sqlite/detail/aggregate_function.hpp deleted file mode 100644 index de0c447..0000000 --- a/include/boost/sqlite/detail/aggregate_function.hpp +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright (c) 2023 Klemens D. Morgenstern -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_SQLITE_DETAIL_AGGREGATE_FUNCTION_HPP -#define BOOST_SQLITE_DETAIL_AGGREGATE_FUNCTION_HPP - -#include <boost/sqlite/detail/config.hpp> -#include <boost/sqlite/detail/catch.hpp> -#include <boost/sqlite/error.hpp> -#include <boost/sqlite/cstring_ref.hpp> -#include <boost/sqlite/memory.hpp> -#include <boost/sqlite/result.hpp> -#include <boost/sqlite/value.hpp> - -#include <boost/callable_traits/args.hpp> -#include <boost/callable_traits/return_type.hpp> -#include <boost/callable_traits/has_void_return.hpp> -#include <boost/core/span.hpp> - - -BOOST_SQLITE_BEGIN_NAMESPACE - -namespace detail -{ - -template<typename Func> -struct aggregate_function_maker -{ - void * mem; - - template<typename ... Args> - Func* operator()(Args && ... args) - { - return new (mem) Func(std::forward<Args>(args)...); - } -}; - -template<typename Func, typename Args> -int create_aggregate_function(sqlite3 * db, cstring_ref name, Args && args, int flags, - std::true_type /* void return */) -{ - using args_type = callable_traits::args_t<decltype(&Func::step)>; - using span_type = typename std::tuple_element<1U, args_type>::type; - using func_type = typename std::decay<Func>::type; - using func_args_type = typename std::decay<Args>::type; - - return sqlite3_create_function_v2( - db, name.c_str(), - span_type::extent == boost::dynamic_extent ? -1 : static_cast<int>(span_type::extent), - SQLITE_UTF8 | flags, - new (memory_tag{}) func_args_type(std::forward<Args>(args)), - nullptr, - +[](sqlite3_context* ctx, int len, sqlite3_value** args) - { - auto aa = reinterpret_cast<value*>(args); - auto fa = reinterpret_cast<func_args_type*>(sqlite3_user_data(ctx)); - auto c = static_cast<func_type*>(sqlite3_aggregate_context(ctx, 0)); - - execute_context_function( - ctx, - [&]() -> result<void> - { - if (c == nullptr) - { - auto p = sqlite3_aggregate_context(ctx, sizeof(func_type)); - if (!p) - return error(SQLITE_NOMEM); - c = mp11::tuple_apply(aggregate_function_maker<func_type>{p}, *fa); - } - c->step(span_type{aa, static_cast<std::size_t>(len)}); - return {}; - }); - }, - [](sqlite3_context* ctx) - { - auto fa = reinterpret_cast<func_args_type*>(sqlite3_user_data(ctx)); - auto c = static_cast<func_type*>(sqlite3_aggregate_context(ctx, 0)); - - execute_context_function( - ctx, - [&]() -> result<decltype(c->final())> - { - if (c == nullptr) - { - auto p = sqlite3_aggregate_context(ctx, sizeof(func_type)); - if (!p) - return error(SQLITE_NOMEM); - c = mp11::tuple_apply(aggregate_function_maker<func_type>{p}, *fa); - } - struct reaper {void operator()(func_type * c) { c->~func_type();}}; - std::unique_ptr<func_type, reaper> cl{c}; - return c->final(); - }); - }, - [](void * ptr) noexcept { delete_(static_cast<func_type*>(ptr));} - ); -} - - -template<typename Func, typename Args> -int create_aggregate_function(sqlite3 * db, cstring_ref name, Args && args, int flags, - std::false_type /* void return */) -{ - using args_type = callable_traits::args_t<decltype(&Func::step)>; - using span_type = typename std::tuple_element<1U, args_type>::type; - using func_type = typename std::decay<Func>::type; - using func_args_type = typename std::decay<Args>::type; - - return sqlite3_create_function_v2( - db, name.c_str(), - span_type::extent == boost::dynamic_extent ? -1 : static_cast<int>(span_type::extent), - SQLITE_UTF8 | flags, - new (memory_tag{}) func_args_type(std::forward<Args>(args)), - nullptr, - +[](sqlite3_context* ctx, int len, sqlite3_value** args) - { - auto aa = reinterpret_cast<value*>(args); - auto fa = reinterpret_cast<func_args_type*>(sqlite3_user_data(ctx)); - auto c = static_cast<func_type*>(sqlite3_aggregate_context(ctx, 0)); - - execute_context_function( - ctx, - [&]() -> result<void> - { - if (c == nullptr) - { - auto p = sqlite3_aggregate_context(ctx, sizeof(func_type)); - if (!p) - return {system::in_place_error, error(SQLITE_NOMEM)}; - c = mp11::tuple_apply(aggregate_function_maker<func_type>{p}, *fa); - } - return c->step(span_type{aa, static_cast<std::size_t>(len)}); - }); - }, - [](sqlite3_context* ctx) - { - auto fa = reinterpret_cast<func_args_type*>(sqlite3_user_data(ctx)); - auto c = static_cast<func_type*>(sqlite3_aggregate_context(ctx, 0)); - - execute_context_function( - ctx, - [&]() -> result<decltype(c->final())> - { - if (c == nullptr) - { - auto p = sqlite3_aggregate_context(ctx, sizeof(func_type)); - if (!p) - return {system::in_place_error, error(SQLITE_NOMEM)}; - c = mp11::tuple_apply(aggregate_function_maker<func_type>{p}, *fa); - } - struct reaper {void operator()(func_type * c) { c->~func_type();}}; - std::unique_ptr<func_type, reaper> cl{c}; - return c->final(); - }); - }, - [](void * ptr) noexcept { delete_(static_cast<func_type*>(ptr));} - ); -} - -} - -BOOST_SQLITE_END_NAMESPACE - - -#endif //BOOST_SQLITE_DETAIL_AGGREGATE_FUNCTION_HPP diff --git a/include/boost/sqlite/detail/catch.hpp b/include/boost/sqlite/detail/catch.hpp deleted file mode 100644 index e5b053f..0000000 --- a/include/boost/sqlite/detail/catch.hpp +++ /dev/null @@ -1,169 +0,0 @@ -// -// Copyright (c) 2022 Klemens Morgenstern (klemens.morgenstern@gmx.net) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_SQLITE_DETAIL_CATCH_HPP -#define BOOST_SQLITE_DETAIL_CATCH_HPP - -#include <boost/sqlite/detail/config.hpp> -#include <boost/sqlite/detail/exception.hpp> -#include <boost/sqlite/error.hpp> -#include <boost/sqlite/result.hpp> - -#include <boost/system/system_error.hpp> - -#include <stdexcept> - - -BOOST_SQLITE_BEGIN_NAMESPACE -namespace detail -{ - -template<typename Func, typename ... Args> -void execute_context_function_impl(std::false_type /* is_void */, - sqlite3_context * ctx, - Func && func, Args && ... args) - noexcept(noexcept(std::forward<Func>(func)(std::forward<Args>(args)...))) -{ - set_result(ctx, std::forward<Func>(func)(std::forward<Args>(args)...)); -} - -template<typename Func, typename ... Args> -void execute_context_function_impl(std::true_type /* is_void */, - sqlite3_context * ctx, - Func && func, Args && ... args) - noexcept(noexcept(std::forward<Func>(func)(std::forward<Args>(args)...))) -{ - std::forward<Func>(func)(std::forward<Args>(args)...); -} - -template<typename T> -int extract_error(char * &errMsg, result<T> & res) -{ - error err = std::move(res).error(); - if (err.info) - errMsg = err.info.release(); - return err.code; -} - - -template<typename Func, typename ... Args> -void execute_context_function(sqlite3_context * ctx, - Func && func, Args && ... args) noexcept -{ - using return_type = decltype(func(std::forward<Args>(args)...)); -#if !defined(BOOST_NO_EXCEPTIONS) - try - { -#endif - execute_context_function_impl(std::is_void<return_type>{}, ctx, - std::forward<Func>(func), - std::forward<Args>(args)...); -#if !defined(BOOST_NO_EXCEPTIONS) - } - catch(boost::system::system_error & se) - { - const auto msg = boost::sqlite::detail::get_message(se); - if (!msg.empty()) - sqlite3_result_error(ctx, msg.data(), msg.size()); - if (se.code().category() == boost::sqlite::sqlite_category()) - sqlite3_result_error_code(ctx, se.code().value()); - } - catch(std::bad_alloc &) { sqlite3_result_error_nomem(ctx); } - catch(std::length_error &) { sqlite3_result_error_toobig(ctx); } - catch(std::out_of_range &) { sqlite3_result_error_code(ctx, SQLITE_RANGE);} - catch(std::logic_error &le) - { - sqlite3_result_error(ctx, le.what(), std::strlen(le.what())); - sqlite3_result_error_code(ctx, SQLITE_MISUSE); - } - catch(std::exception & ex) - { - sqlite3_result_error(ctx, ex.what(), std::strlen(ex.what())); - } - catch(...) {sqlite3_result_error_code(ctx, SQLITE_ERROR); } -#endif -} - -} -BOOST_SQLITE_END_NAMESPACE - -#if defined(BOOST_NO_EXCEPTIONS) -#define BOOST_SQLITE_TRY -#define BOOST_SQLITE_CATCH_RESULT(ctx) -#define BOOST_SQLITE_CATCH_ASSIGN_STR_AND_RETURN(msg) -#define BOOST_SQLITE_CATCH_AND_RETURN() - -#else - -#define BOOST_SQLITE_TRY try -#define BOOST_SQLITE_CATCH_RESULT(ctx) \ -catch(boost::system::system_error & se) \ -{ \ - if (se.code().category() == boost::sqlite::sqlite_category()) \ - sqlite3_result_error_code(ctx, se.code().value()); \ - const auto msg = boost::sqlite::detail::get_message(se); \ - if (!msg.empty()) \ - sqlite3_result_error(ctx, msg.data(), msg.size()); \ -} \ -catch(std::bad_alloc &) { sqlite3_result_error_nomem(ctx); } \ -catch(std::length_error &) { sqlite3_result_error_toobig(ctx); } \ -catch(std::out_of_range &) { sqlite3_result_error_code(ctx, SQLITE_RANGE);} \ -catch(std::logic_error &le) \ -{ \ - sqlite3_result_error(ctx, le.what(), std::strlen(le.what())); \ - sqlite3_result_error_code(ctx, SQLITE_MISUSE); \ -} \ -catch(std::exception & ex) \ -{ \ - sqlite3_result_error(ctx, ex.what(), std::strlen(ex.what())); \ -} \ -catch(...) {sqlite3_result_error_code(ctx, SQLITE_ERROR); } - - -#define BOOST_SQLITE_CATCH_ASSIGN_STR_AND_RETURN(msg) \ -catch (boost::system::system_error & se) \ -{ \ - auto code = SQLITE_ERROR; \ - if (se.code().category() == boost::sqlite::sqlite_category()) \ - code = se.code().value(); \ - const auto pre = boost::sqlite::detail::get_message(se); \ - msg = boost::sqlite::error_info(pre).release(); \ - return code; \ -} \ -catch(std::bad_alloc &) { return SQLITE_NOMEM; } \ -catch(std::length_error &) { return SQLITE_TOOBIG; } \ -catch(std::out_of_range &) { return SQLITE_RANGE;} \ -catch(std::logic_error &le) \ -{ \ - msg = boost::sqlite::error_info(le.what()).release(); \ - return SQLITE_MISUSE; \ -} \ -catch(std::exception & ex) \ -{ \ - msg = boost::sqlite::error_info(ex.what()).release(); \ - return SQLITE_ERROR; \ -} \ -catch(...) {return SQLITE_ERROR; } \ - - -#define BOOST_SQLITE_CATCH_AND_RETURN() \ -catch (boost::system::system_error & se) \ -{ \ - auto code = SQLITE_ERROR; \ - if (se.code().category() == boost::sqlite::sqlite_category()) \ - code = se.code().value(); \ - return code; \ -} \ -catch(std::bad_alloc &) { return SQLITE_NOMEM; } \ -catch(std::length_error &) { return SQLITE_TOOBIG; } \ -catch(std::out_of_range &) { return SQLITE_RANGE;} \ -catch(std::logic_error &) { return SQLITE_MISUSE;} \ -catch(...) { return SQLITE_ERROR; } \ - -#endif - -#endif //BOOST_SQLITE_DETAIL_CATCH_HPP diff --git a/include/boost/sqlite/detail/config.hpp b/include/boost/sqlite/detail/config.hpp deleted file mode 100644 index 2126f60..0000000 --- a/include/boost/sqlite/detail/config.hpp +++ /dev/null @@ -1,83 +0,0 @@ -// -// Copyright (c) 2022 Klemens Morgenstern (klemens.morgenstern@gmx.net) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_SQLITE_DETAIL_CONFIG_HPP -#define BOOST_SQLITE_DETAIL_CONFIG_HPP - -#include <boost/config.hpp> -#include <boost/core/detail/string_view.hpp> - -#if defined(BOOST_SQLITE_COMPILE_EXTENSION) -#include <sqlite3ext.h> -#define BOOST_SQLITE_COMPILING_EXTENSION 1 -#define BOOST_SQLITE_BEGIN_NAMESPACE namespace boost { namespace sqlite { inline namespace ext { -#define BOOST_SQLITE_END_NAMESPACE } } } -#else -#include <sqlite3.h> -#define BOOST_SQLITE_BEGIN_NAMESPACE namespace boost { namespace sqlite { -#define BOOST_SQLITE_END_NAMESPACE } } -#endif - -// copied from boost.json -#if defined(BOOST_SQLITE_DOCS) -# define BOOST_SQLITE_DECL -#else -# if (defined(BOOST_SQLITE_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)) && !defined(BOOST_SQLITE_STATIC_LINK) -# if defined(BOOST_SQLITE_SOURCE) -# define BOOST_SQLITE_DECL BOOST_SYMBOL_EXPORT -# else -# define BOOST_SQLITE_DECL BOOST_SYMBOL_IMPORT -# endif -# endif // static lib -# ifndef BOOST_SQLITE_DECL -# define BOOST_SQLITE_DECL -# endif -# if !defined(BOOST_SQLITE_SOURCE) && !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_SQLITE_NO_LIB) -# define BOOST_LIB_NAME boost_sqlite -# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_SQLITE_DYN_LINK) -# define BOOST_DYN_LINK -# endif -# include <boost/config/auto_link.hpp> -# endif -#endif - -BOOST_SQLITE_BEGIN_NAMESPACE - - -#if defined(BOOST_SQLITE_COMPILE_EXTENSION) -extern const sqlite3_api_routines *sqlite3_api; -#endif - -using string_view = boost::core::string_view; - -BOOST_SQLITE_END_NAMESPACE - -#define BOOST_SQLITE_RETURN_EC(ev) \ -do \ -{ \ - static constexpr auto loc##__LINE__((BOOST_CURRENT_LOCATION)); \ - return ::boost::system::error_code(ev, boost::sqlite::sqlite_category(), &loc##__LINE__); \ -} \ -while (false) - -#define BOOST_SQLITE_ASSIGN_EC(ec, ev) \ -do \ -{ \ - static constexpr auto loc##__LINE__((BOOST_CURRENT_LOCATION)); \ - ec.assign(ev, boost::sqlite::sqlite_category(), &loc##__LINE__); \ -} \ -while (false) - -#if defined(BOOST_SQLITE_NO_VIRTUAL) -#define BOOST_SQLITE_VIRTUAL -#define BOOST_SQLITE_PURE -#else -#define BOOST_SQLITE_VIRTUAL virtual -#define BOOST_SQLITE_PURE = 0 -#endif - -#endif // BOOST_SQLITE_DETAIL_HPP
\ No newline at end of file diff --git a/include/boost/sqlite/detail/exception.hpp b/include/boost/sqlite/detail/exception.hpp deleted file mode 100644 index 9f29cbe..0000000 --- a/include/boost/sqlite/detail/exception.hpp +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2023 Klemens D. Morgenstern -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_SQLITE_DETAIL_EXCEPTION_HPP -#define BOOST_SQLITE_DETAIL_EXCEPTION_HPP - -#include <boost/sqlite/detail/config.hpp> -#include <boost/sqlite/error.hpp> - -BOOST_SQLITE_BEGIN_NAMESPACE -namespace detail -{ - -BOOST_SQLITE_DECL -BOOST_NORETURN void throw_error_code(const boost::system::error_code & ec, - const boost::source_location & loc = BOOST_CURRENT_LOCATION); - -BOOST_SQLITE_DECL -BOOST_NORETURN void throw_error_code(const boost::system::error_code & ec, - const error_info & ei, - const boost::source_location & loc = BOOST_CURRENT_LOCATION); - -BOOST_SQLITE_DECL -BOOST_NORETURN void throw_out_of_range(const char * msg, - const boost::source_location & loc); - -BOOST_SQLITE_DECL -BOOST_NORETURN void throw_invalid_argument(const char * msg, - const boost::source_location & loc); - -inline core::string_view get_message(const system::system_error & se) -{ - auto ec_len = se.code().what().size(); - auto se_len = std::strlen(se.what()); - - if (ec_len == se_len) - return core::string_view(); - else - return core::string_view(se.what(), se_len - (ec_len + 2)); -} - - -} -BOOST_SQLITE_END_NAMESPACE - - -#endif //BOOST_SQLITE_DETAIL_EXCEPTION_HPP diff --git a/include/boost/sqlite/detail/scalar_function.hpp b/include/boost/sqlite/detail/scalar_function.hpp deleted file mode 100644 index ee16a23..0000000 --- a/include/boost/sqlite/detail/scalar_function.hpp +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright (c) 2023 Klemens D. Morgenstern -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_SQLITE_DETAIL_SCALAR_FUNCTION_HPP -#define BOOST_SQLITE_DETAIL_SCALAR_FUNCTION_HPP - -#include <boost/sqlite/detail/config.hpp> -#include <boost/sqlite/cstring_ref.hpp> -#include <boost/sqlite/memory.hpp> -#include <boost/sqlite/result.hpp> -#include <boost/sqlite/value.hpp> - -#include <boost/callable_traits/args.hpp> -#include <boost/callable_traits/return_type.hpp> -#include <boost/callable_traits/has_void_return.hpp> -#include <boost/core/span.hpp> - - -BOOST_SQLITE_BEGIN_NAMESPACE - -template<typename ... Args> -struct context; - -namespace detail -{ - -template<typename Func, typename ... Args, std::size_t Extent> -auto create_scalar_function_impl(sqlite3 * db, - cstring_ref name, - Func && func, - int flags, - std::tuple<context<Args...>, boost::span<value, Extent>> * , - std::false_type /* void return */, - std::false_type /* is pointer */) -> int -{ - using func_type = typename std::decay<Func>::type; - return sqlite3_create_function_v2( - db, name.c_str(), - Extent == boost::dynamic_extent ? -1 : static_cast<int>(Extent), - SQLITE_UTF8 | flags, - new (memory_tag{}) func_type(std::forward<Func>(func)), - +[](sqlite3_context* ctx, int len, sqlite3_value** args) - { - auto cc = context<Args...>(ctx); - auto aa = reinterpret_cast<value*>(args); - auto &f = *reinterpret_cast<func_type*>(sqlite3_user_data(ctx)); - boost::span<value, Extent> vals{aa, static_cast<std::size_t>(len)}; - - execute_context_function(ctx, f, cc, vals); - }, nullptr, nullptr, - +[](void * ptr) noexcept {delete_(static_cast<func_type*>(ptr));} - ); -} - -template<typename Func, typename ... Args, std::size_t Extent> -auto create_scalar_function_impl(sqlite3 * db, - cstring_ref name, - Func && func, int flags, - std::tuple<context<Args...>, boost::span<value, Extent>> * , - std::true_type /* void return */, - std::false_type /* is pointer */) -> int -{ - using func_type = typename std::decay<Func>::type; - return sqlite3_create_function_v2( - db, - name.c_str(), - (Extent == boost::dynamic_extent) ? -1 : static_cast<int>(Extent), - SQLITE_UTF8 | flags, - new (memory_tag{}) func_type(std::forward<Func>(func)), - +[](sqlite3_context* ctx, int len, sqlite3_value** args) - { - auto cc = context<Args...>(ctx); - auto aa = reinterpret_cast<value*>(args); - auto &f = *reinterpret_cast<func_type*>(sqlite3_user_data(ctx)); - boost::span<value, Extent> vals{aa, static_cast<std::size_t>(len)}; - - execute_context_function( - ctx, - [&]() - { - f(cc, vals); - return result<void>(); - }); - - }, nullptr, nullptr, - +[](void * ptr){delete_(static_cast<func_type*>(ptr));} - ); -} - - -template<typename Func, typename ... Args, std::size_t Extent> -auto create_scalar_function_impl(sqlite3 * db, - cstring_ref name, - Func * func, int flags, - std::tuple<context<Args...>, boost::span<value, Extent>> * , - std::false_type /* void return */, - std::true_type /* is pointer */) -> int -{ - return sqlite3_create_function_v2( - db, name.c_str(), - Extent == boost::dynamic_extent ? -1 : static_cast<int>(Extent), - SQLITE_UTF8 | flags, - reinterpret_cast<void*>(func), - +[](sqlite3_context* ctx, int len, sqlite3_value** args) - { - auto cc = context<Args...>(ctx); - auto aa = reinterpret_cast<value*>(args); - auto f = reinterpret_cast<Func*>(sqlite3_user_data(ctx)); - - boost::span<value, Extent> vals{aa, static_cast<std::size_t>(len)}; - - execute_context_function( - ctx, f, cc, vals); - }, nullptr, nullptr, nullptr); -} - -template<typename Func, typename ... Args, std::size_t Extent> -auto create_scalar_function_impl(sqlite3 * db, - cstring_ref name, - Func * func, int flags, - std::tuple<context<Args...>, boost::span<value, Extent>> * , - std::true_type /* void return */, - std::true_type /* is pointer */) -> int -{ - return sqlite3_create_function_v2( - db, - name.c_str(), - (Extent == boost::dynamic_extent) ? -1 : static_cast<int>(Extent), - SQLITE_UTF8 | flags, - reinterpret_cast<void*>(func), - +[](sqlite3_context* ctx, int len, sqlite3_value** args) - { - auto cc = context<Args...>(ctx); - auto aa = reinterpret_cast<value*>(args); - auto f = *reinterpret_cast<Func*>(sqlite3_user_data(ctx)); - boost::span<value, Extent> vals{aa, static_cast<std::size_t>(len)}; - execute_context_function( - ctx, - [&]() - { - f(cc, vals); - return result<void>(); - }); - - }, nullptr, nullptr, nullptr); -} - -template<typename Func> -auto create_scalar_function(sqlite3 * db, - cstring_ref name, - Func && func, - int flags) - -> decltype(create_scalar_function_impl( - db, name, std::forward<Func>(func), flags, - static_cast<callable_traits::args_t<Func>*>(nullptr), - callable_traits::has_void_return<Func>{}, - std::is_pointer<typename std::decay<Func>::type>{} - )) -{ - return create_scalar_function_impl(db, name, std::forward<Func>(func), flags, - static_cast<callable_traits::args_t<Func>*>(nullptr), - callable_traits::has_void_return<Func>{}, - std::is_pointer<typename std::decay<Func>::type>{}); -} - - -} - -BOOST_SQLITE_END_NAMESPACE - -#endif //BOOST_SQLITE_DETAIL_SCALAR_FUNCTION_HPP diff --git a/include/boost/sqlite/detail/vtable.hpp b/include/boost/sqlite/detail/vtable.hpp deleted file mode 100644 index f85f44c..0000000 --- a/include/boost/sqlite/detail/vtable.hpp +++ /dev/null @@ -1,611 +0,0 @@ -// Copyright (c) 2023 Klemens D. Morgenstern -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_SQLITE_DETAIL_VTABLE_HPP -#define BOOST_SQLITE_DETAIL_VTABLE_HPP - -#include <boost/sqlite/detail/config.hpp> -#include <boost/sqlite/detail/catch.hpp> -#include <boost/sqlite/vtable.hpp> - -BOOST_SQLITE_BEGIN_NAMESPACE -namespace detail -{ -struct vtab_impl -{ - -template<typename Module> -static int connect(sqlite3 * db, void * pAux, int argc, const char * const * argv, - sqlite3_vtab **ppVTab, char** errMsg) -{ - using table_type = typename Module::table_type; - auto &impl = *static_cast<Module*>(pAux); - BOOST_SQLITE_TRY - { - result<table_type> rtab = impl.connect( - sqlite::connection(db, false), - argc, argv); - - if (rtab.has_error()) - return extract_error(*errMsg, rtab); - - auto tab = make_unique<table_type>(std::move(*rtab)); - tab->db_ = db; - auto code = sqlite3_declare_vtab(db, tab->declaration()); - if (code != SQLITE_OK) - return code; - - sqlite::vtab::module_config cfg{db}; - auto r = tab->config(cfg); - if (r.has_error()) - return extract_error(*errMsg, r); - - *ppVTab = tab.release(); - - return SQLITE_OK; - } - BOOST_SQLITE_CATCH_ASSIGN_STR_AND_RETURN(*errMsg) -} - - -template<typename Module> -static int create(sqlite3 * db, void * pAux, int argc, const char * const * argv, - sqlite3_vtab **ppVTab, char** errMsg) -{ - using table_type = typename Module::table_type; - auto &impl = *static_cast<Module*>(pAux); - BOOST_SQLITE_TRY - { - result<table_type> rtab = impl.create( - sqlite::connection(db, false), - argc, argv); - - if (rtab.has_error()) - return extract_error(*errMsg, rtab); - - auto tab = make_unique<table_type>(std::move(*rtab)); - tab->db_ = db; - - auto code = sqlite3_declare_vtab(db, tab->declaration()); - if (code != SQLITE_OK) - return code; - - sqlite::vtab::module_config mc{db}; - auto r = tab->config(mc); - if (r.has_error()) - return extract_error(*errMsg, r); - - *ppVTab = tab.release(); - - return SQLITE_OK; - } - BOOST_SQLITE_CATCH_ASSIGN_STR_AND_RETURN(*errMsg) -} - -template<typename Table> -static int disconnect(sqlite3_vtab * tab) -{ - BOOST_SQLITE_TRY - { - auto tb = static_cast<Table*>(tab); - tb->~Table(); - sqlite3_free(tb); - return SQLITE_OK; - } - BOOST_SQLITE_CATCH_ASSIGN_STR_AND_RETURN(tab->zErrMsg); -} - -template<typename Table> -static int destroy(sqlite3_vtab * tab) -{ - BOOST_SQLITE_TRY - { - auto tb = static_cast<Table*>(tab); - auto res = tb->destroy(); - tb->~Table(); - sqlite3_free(tb); - if (res.has_error()) - return std::move(res).error().code; - return SQLITE_OK; - } - BOOST_SQLITE_CATCH_ASSIGN_STR_AND_RETURN(tab->zErrMsg); -} - -template<typename Module, typename Table> -static void assign_create(sqlite3_module & md, const Module &, - const sqlite::vtab::eponymous_module<Table> & base) -{ - md.xConnect = md.xCreate = &connect<Module>; - md.xDisconnect = md.xDestroy = &disconnect<Table>; - if (base.eponymous_only()) - md.xCreate = nullptr; -} - -template<typename Module, typename Table> -static void assign_create(sqlite3_module & md, const Module &, - const sqlite::vtab::module<Table> &) -{ - md.xConnect = &connect<Module>; - md.xDisconnect = &disconnect<Table>; - md.xCreate = &create<Module>; - md.xDestroy = &destroy<Table>; -} - -template<typename Table> -static int open(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor) -{ - auto tab = static_cast<Table *>(pVTab); - - BOOST_SQLITE_TRY - { - auto res = tab->open(); - if (res.has_error()) - return extract_error(pVTab->zErrMsg, res); - *ppCursor = new (memory_tag{}) typename Table::cursor_type(std::move(*res)); - return SQLITE_OK; - } - BOOST_SQLITE_CATCH_AND_RETURN(); -} - -template<typename Cursor> -static int close(sqlite3_vtab_cursor * cursor) -{ - auto p = static_cast<Cursor *>(cursor); - - BOOST_SQLITE_TRY - { - p->~Cursor(); - } - BOOST_SQLITE_CATCH_AND_RETURN(); - - sqlite3_free(p); - return SQLITE_OK; - -} - -template<typename Table> -static int best_index(sqlite3_vtab *pVTab, sqlite3_index_info* info) -{ - BOOST_SQLITE_TRY - { - auto tb = static_cast<Table*>(pVTab); - - sqlite::vtab::index_info ii(tb->db_, info); - auto r = tb->best_index(ii); - if (r.has_error()) - return extract_error(pVTab->zErrMsg, r); - - return SQLITE_OK; - } - BOOST_SQLITE_CATCH_ASSIGN_STR_AND_RETURN(pVTab->zErrMsg); -} - - -template<typename Cursor> -static int filter(sqlite3_vtab_cursor* pCursor, - int idxNum, const char *idxStr, - int argc, sqlite3_value **argv) -{ - BOOST_SQLITE_TRY - { - auto cr = static_cast<Cursor*>(pCursor); - - auto r = cr->filter(idxNum, idxStr, - boost::span<value>{reinterpret_cast<value*>(argv), - static_cast<std::size_t>(argc)}); - if (r.has_error()) - return extract_error(pCursor->pVtab->zErrMsg, r); - - return SQLITE_OK; - } - BOOST_SQLITE_CATCH_ASSIGN_STR_AND_RETURN(pCursor->pVtab->zErrMsg); -} - - -template<typename Cursor> -static int next(sqlite3_vtab_cursor* pCursor) -{ - BOOST_SQLITE_TRY - { - auto cr = static_cast<Cursor*>(pCursor); - - auto r = cr->next(); - if (r.has_error()) - return extract_error(pCursor->pVtab->zErrMsg, r); - - return SQLITE_OK; - } - BOOST_SQLITE_CATCH_ASSIGN_STR_AND_RETURN(pCursor->pVtab->zErrMsg); -} - - -template<typename Cursor> -static int eof(sqlite3_vtab_cursor* pCursor) -{ - return static_cast<Cursor*>(pCursor)->eof() ? 1 : 0; -} - -template<typename Cursor> -static auto column(sqlite3_vtab_cursor* pCursor, - sqlite3_context * ctx, int idx) - -> typename std::enable_if<!std::is_void<typename Cursor::column_type>::value, int>::type -{ -#if SQLITE_VERSION_NUMBER >= 3032000 - bool no_change = sqlite3_vtab_nochange(ctx) != 0; -#else - bool no_change = false; -#endif - auto cr = static_cast<Cursor*>(pCursor); - execute_context_function( - ctx, - [&]{ - return cr->column(idx, no_change); - }); - - return SQLITE_OK; -} - - -template<typename Cursor> -static auto column(sqlite3_vtab_cursor* pCursor, - sqlite3_context * ctx, int idx) - -> typename std::enable_if<std::is_void<typename Cursor::column_type>::value, int>::type -{ -#if SQLITE_VERSION_NUMBER >= 3032000 - bool no_change = sqlite3_vtab_nochange(ctx) != 0; -#else - bool no_change = false; -#endif - auto cr = static_cast<Cursor*>(pCursor); - BOOST_SQLITE_TRY - { - cr->column(context<>{ctx}, idx, no_change); - } - BOOST_SQLITE_CATCH_RESULT(ctx); - return SQLITE_OK; -} - -template<typename Cursor> -static int row_id(sqlite3_vtab_cursor* pCursor, sqlite3_int64 *pRowid) -{ - BOOST_SQLITE_TRY - { - auto cr = static_cast<Cursor*>(pCursor); - - auto r = cr->row_id(); - if (r.has_error()) - return extract_error(pCursor->pVtab->zErrMsg, r); - *pRowid = *r; - return SQLITE_OK; - } - BOOST_SQLITE_CATCH_ASSIGN_STR_AND_RETURN(pCursor->pVtab->zErrMsg); -} - -template<typename Table> -static int update(sqlite3_vtab * pVTab, int argc, sqlite3_value ** argv, sqlite3_int64 * pRowid) -{ - using table_type = Table; - BOOST_SQLITE_TRY - { - auto & mod = *static_cast<table_type *>(pVTab); - auto db = mod.db_; - if (argc == 1 && sqlite3_value_type(argv[0]) != SQLITE_NULL) - { - auto r = mod.delete_(sqlite::value(*argv)); - if (r.has_error()) - return extract_error(pVTab->zErrMsg, r); - } - else if (argc > 1 && sqlite3_value_type(argv[0]) == SQLITE_NULL) - { - auto r = mod.insert(value{argv[1]}, - boost::span<value>{reinterpret_cast<value *>(argv + 2), - static_cast<std::size_t>(argc - 2)}, - sqlite3_vtab_on_conflict(db)); - if (r.has_error()) - return extract_error(pVTab->zErrMsg, r); - *pRowid = r.value(); - } - else if (argc > 1 && sqlite3_value_type(argv[0]) != SQLITE_NULL) - { - auto r = mod.update(sqlite::value(*argv), value{argv[1]}, // ID - boost::span<value>{reinterpret_cast<value *>(argv + 2), - static_cast<std::size_t>(argc - 2)}, - sqlite3_vtab_on_conflict(db)); - - if (r.has_error()) - return extract_error(pVTab->zErrMsg, r); - *pRowid = r.value(); - } - else - { - pVTab->zErrMsg = sqlite3_mprintf("Misuse of update api"); - return SQLITE_MISUSE; - } - - } - BOOST_SQLITE_CATCH_ASSIGN_STR_AND_RETURN(pVTab->zErrMsg) - return SQLITE_OK; -} - -template<typename Module> -static void assign_update(sqlite3_module & md, const Module &, - std::true_type /* modifiable */) -{ - md.xUpdate = &update<typename Module::table_type>; -} - -template<typename Module> -static void assign_update(sqlite3_module & /*md*/, const Module &, - std::false_type /* modifiable */) -{ -} - -template<typename Table> -static int begin(sqlite3_vtab* pVTab) -{ - BOOST_SQLITE_TRY - { - auto cr = static_cast<Table*>(pVTab); - - auto r = cr->begin(); - if (r.has_error()) - return extract_error(pVTab->zErrMsg, r); - - return SQLITE_OK; - } - BOOST_SQLITE_CATCH_ASSIGN_STR_AND_RETURN(pVTab->zErrMsg); -} - -template<typename Table> -static int sync(sqlite3_vtab* pVTab) -{ - BOOST_SQLITE_TRY - { - auto cr = static_cast<Table*>(pVTab); - - auto r = cr->sync(); - if (r.has_error()) - return extract_error(pVTab->zErrMsg, r); - - return SQLITE_OK; - } - BOOST_SQLITE_CATCH_ASSIGN_STR_AND_RETURN(pVTab->zErrMsg); -} - -template<typename Table> -static int commit(sqlite3_vtab* pVTab) -{ - BOOST_SQLITE_TRY - { - auto cr = static_cast<Table*>(pVTab); - - auto r = cr->commit(); - if (r.has_error()) - return extract_error(pVTab->zErrMsg, r); - - return SQLITE_OK; - } - BOOST_SQLITE_CATCH_ASSIGN_STR_AND_RETURN(pVTab->zErrMsg); -} - -template<typename Table> -static int rollback(sqlite3_vtab* pVTab) -{ - BOOST_SQLITE_TRY - { - auto cr = static_cast<Table*>(pVTab); - - auto r = cr->rollback(); - if (r.has_error()) - return extract_error(pVTab->zErrMsg, r); - - return SQLITE_OK; - } - BOOST_SQLITE_CATCH_ASSIGN_STR_AND_RETURN(pVTab->zErrMsg); -} - -template<typename Module> -static void assign_transaction(sqlite3_module & /*md*/, const Module &, - std::false_type /* modifiable */) -{ -} - -template<typename Module> -static void assign_transaction(sqlite3_module & md, const Module &, - std::true_type /* modifiable */) -{ - md.xBegin = &begin <typename Module::table_type>; - md.xSync = &sync <typename Module::table_type>; - md.xCommit = &commit <typename Module::table_type>; - md.xRollback = &rollback<typename Module::table_type>; -} - -template<typename Table> -static int find_function(sqlite3_vtab *pVtab, int nArg, const char *zName, - void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), - void **ppArg) -{ - BOOST_SQLITE_TRY - { - auto cr = static_cast<Table*>(pVtab); - - auto r = cr->find_function( - nArg, zName, sqlite::vtab::function_setter(pxFunc, ppArg)); - if (r.has_error()) - return extract_error(pVtab->zErrMsg, r); - - return SQLITE_OK; - } - BOOST_SQLITE_CATCH_ASSIGN_STR_AND_RETURN(pVtab->zErrMsg); -} - -template<typename Module> -static void assign_find_function(sqlite3_module & /*md*/, const Module &, - std::false_type /* overloadable */) -{ -} - -template<typename Module> -static void assign_find_function(sqlite3_module & md, const Module &, - std::true_type /* overloadable */) -{ - md.xFindFunction = &find_function<typename Module::table_type>; -} - -template<typename Table> -static int rename(sqlite3_vtab* pVTab, const char * name) -{ - BOOST_SQLITE_TRY - { - auto cr = static_cast<Table*>(pVTab); - - auto r = cr->rename(name); - if (r.has_error()) - return extract_error(pVTab->zErrMsg, r); - - return SQLITE_OK; - } - BOOST_SQLITE_CATCH_ASSIGN_STR_AND_RETURN(pVTab->zErrMsg); -} - -template<typename Module> -static void assign_rename(sqlite3_module & /*md*/, const Module &, - std::false_type /* renamable */) -{ -} - -template<typename Module> -static void assign_rename(sqlite3_module & md, const Module &, - std::true_type /* renamable */) -{ - md.xRename = &rename<typename Module::table_type>; -} -#if SQLITE_VERSION_NUMBER >= 3007007 - -template<typename Table> -static int savepoint(sqlite3_vtab* pVTab, int i) -{ - BOOST_SQLITE_TRY - { - auto cr = static_cast<Table*>(pVTab); - - auto r = cr->savepoint(i); - if (r.has_error()) - return extract_error(pVTab->zErrMsg, r); - - return SQLITE_OK; - } - BOOST_SQLITE_CATCH_ASSIGN_STR_AND_RETURN(pVTab->zErrMsg); -} - -template<typename Table> -static int release(sqlite3_vtab* pVTab, int i) -{ - BOOST_SQLITE_TRY - { - auto cr = static_cast<Table*>(pVTab); - - auto r = cr->release(i); - if (r.has_error()) - return extract_error(pVTab->zErrMsg, r); - - return SQLITE_OK; - } - BOOST_SQLITE_CATCH_ASSIGN_STR_AND_RETURN(pVTab->zErrMsg); -} - -template<typename Table> -static int rollback_to(sqlite3_vtab* pVTab, int i) -{ - BOOST_SQLITE_TRY - { - auto cr = static_cast<Table*>(pVTab); - - auto r = cr->rollback_to(i); - if (r.has_error()) - return extract_error(pVTab->zErrMsg, r); - - return SQLITE_OK; - } - BOOST_SQLITE_CATCH_ASSIGN_STR_AND_RETURN(pVTab->zErrMsg); -} - -template<typename Module> -static void assign_recursive_transaction(sqlite3_module & /*md*/, const Module &, - std::false_type /* recursive_transaction */) -{ -} - -template<typename Module> -static void assign_recursive_transaction(sqlite3_module & md, const Module &, - std::true_type /* recursive_transaction */) -{ - md.xSavepoint = &savepoint <typename Module::table_type>; - md.xRelease = &release <typename Module::table_type>; - md.xRollbackTo = &rollback_to<typename Module::table_type>; -} - -#endif - -#if SQLITE_VERSION_NUMBER >= 3026000 - -template<typename Table> -static void assign_shadow_name(sqlite3_module & /*md*/, const sqlite::vtab::module<Table> &) {} - -template<typename Table> -static void assign_shadow_name(sqlite3_module & /*md*/, const sqlite::vtab::eponymous_module<Table> &) {} - -template<typename Module, - bool (*Func)(const char *) = &Module::shadow_name> -static void assign_shadow_name(sqlite3_module & md, const Module & mod) -{ - md.xShadowName = +[](const char * name){return Func(name) != 0;}; -} - -#endif - -}; - -template<typename Module> -const sqlite3_module make_module(const Module & mod) -{ - sqlite3_module md; - std::memset(&md, 0, sizeof(sqlite3_module)); - -#if SQLITE_VERSION_NUMBER < 3007007 - md.iVersion = 1; -#elif SQLITE_VERSION_NUMBER < 3026000 - md.iVersion = 2; -#else - md.iVersion = 3; -#endif - using table_type = typename Module::table_type; - using cursor_type = typename table_type::cursor_type; - vtab_impl::assign_create(md, mod, mod); - md.xBestIndex = &vtab_impl::best_index<table_type>; - md.xOpen = &vtab_impl::open <table_type>; - md.xClose = &vtab_impl::close <cursor_type>; - md.xFilter = &vtab_impl::filter <cursor_type>; - md.xNext = &vtab_impl::next <cursor_type>; - md.xEof = &vtab_impl::eof <cursor_type>; - md.xColumn = &vtab_impl::column <cursor_type>; - md.xRowid = &vtab_impl::row_id <cursor_type>; - vtab_impl::assign_update (md, mod, std::is_base_of<sqlite::vtab::modifiable, table_type>{}); - vtab_impl::assign_transaction (md, mod, std::is_base_of<sqlite::vtab::transaction, table_type>{}); - vtab_impl::assign_find_function(md, mod, std::is_base_of<sqlite::vtab::overload_functions, table_type>{}); - vtab_impl::assign_rename (md, mod, std::is_base_of<sqlite::vtab::renamable, table_type>{}); -#if SQLITE_VERSION_NUMBER >= 3007007 - vtab_impl::assign_recursive_transaction(md, mod, std::is_base_of<sqlite::vtab::recursive_transaction, table_type>{}); -#endif -#if SQLITE_VERSION_NUMBER >= 3026000 - vtab_impl::assign_shadow_name(md, mod); -#endif - return md; -} - -} - -BOOST_SQLITE_END_NAMESPACE - -#endif //BOOST_SQLITE_DETAIL_VTABLE_HPP diff --git a/include/boost/sqlite/detail/window_function.hpp b/include/boost/sqlite/detail/window_function.hpp deleted file mode 100644 index df8475c..0000000 --- a/include/boost/sqlite/detail/window_function.hpp +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright (c) 2023 Klemens D. Morgenstern -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_SQLITE_IMPL_WINDOW_FUNCTION_HPP -#define BOOST_SQLITE_IMPL_WINDOW_FUNCTION_HPP -#if SQLITE_VERSION_NUMBER >= 3025000 - -#include <boost/sqlite/detail/config.hpp> -#include <boost/sqlite/cstring_ref.hpp> -#include <boost/sqlite/memory.hpp> -#include <boost/sqlite/result.hpp> -#include <boost/sqlite/value.hpp> - -BOOST_SQLITE_BEGIN_NAMESPACE - -namespace detail -{ - -template<typename Func> -struct window_function_maker -{ - void * mem; - - template<typename ... Args> - Func* operator()(Args && ... args) - { - return new (mem) Func(std::forward<Args>(args)...); - } -}; - -template<typename Func, typename Args> -int create_window_function(sqlite3 * db, cstring_ref name, Args && args, int flags, - std::true_type /* is void */) -{ - using args_type = callable_traits::args_t<decltype(&Func::step)>; - using span_type = typename std::tuple_element<1U, args_type>::type; - using func_type = typename std::decay<Func>::type; - using func_args_type = typename std::decay<Args>::type; - - return sqlite3_create_window_function( - db, name.c_str(), - span_type::extent == boost::dynamic_extent ? -1 : static_cast<int>(span_type::extent), - SQLITE_UTF8 | flags, - new (memory_tag{}) func_args_type(std::forward<Args>(args)), - +[](sqlite3_context* ctx, int len, sqlite3_value** args) noexcept //xStep - { - auto aa = reinterpret_cast<value*>(args); - auto fa = reinterpret_cast<func_args_type*>(sqlite3_user_data(ctx)); - auto c = static_cast<func_type*>(sqlite3_aggregate_context(ctx, 0)); - - execute_context_function( - ctx, - [&]() -> result<void> - { - if (c == nullptr) - { - auto p = sqlite3_aggregate_context(ctx, sizeof(func_type)); - if (!p) - return error(SQLITE_NOMEM); - c = mp11::tuple_apply(window_function_maker<func_type>{p}, *fa); - } - c->step(span_type{aa, static_cast<std::size_t>(len)}); - return {}; - }); - - }, - [](sqlite3_context* ctx) // xFinal - { - auto fa = reinterpret_cast<func_args_type*>(sqlite3_user_data(ctx)); - auto c = static_cast<func_type*>(sqlite3_aggregate_context(ctx, 0)); - - execute_context_function( - ctx, - [&]() -> result<decltype(c->value())> - { - if (c == nullptr) - { - auto p = sqlite3_aggregate_context(ctx, sizeof(func_type)); - if (!p) - return error(SQLITE_NOMEM); - c = mp11::tuple_apply(window_function_maker<func_type>{p}, *fa); - } - struct reaper {void operator()(func_type * c) { c->~func_type();}}; - std::unique_ptr<func_type, reaper> cl{c}; - - return c->value(); - }); - }, - [](sqlite3_context* ctx) //xValue - { - auto fa = reinterpret_cast<func_args_type*>(sqlite3_user_data(ctx)); - auto c = static_cast<func_type*>(sqlite3_aggregate_context(ctx, 0)); - execute_context_function( - ctx, - [&]() -> result<decltype(c->value())> - { - if (c == nullptr) - { - auto p = sqlite3_aggregate_context(ctx, sizeof(func_type)); - if (!p) - return error(SQLITE_NOMEM); - c = mp11::tuple_apply(window_function_maker<func_type>{p}, *fa); - } - return c->value(); - }); - - }, - +[](sqlite3_context* ctx, int len, sqlite3_value** args) // xInverse - { - auto aa = reinterpret_cast<value*>(args); - auto fa = reinterpret_cast<func_args_type*>(sqlite3_user_data(ctx)); - auto c = static_cast<func_type*>(sqlite3_aggregate_context(ctx, 0)); - execute_context_function( - ctx, - [&]() -> result<decltype(c->inverse(span_type{aa, static_cast<std::size_t>(len)}))> - { - if (c == nullptr) - { - auto p = sqlite3_aggregate_context(ctx, sizeof(func_type)); - if (!p) - return error(SQLITE_NOMEM); - c = mp11::tuple_apply(window_function_maker<func_type>{p}, *fa); - } - c->inverse(span_type{aa, static_cast<std::size_t>(len)}); - return {}; - }); - - }, - [](void * ptr) /* xDestroy */ { delete_(static_cast<func_type*>(ptr));} - ); -} - -template<typename Func, typename Args> -int create_window_function(sqlite3 * db, cstring_ref name, Args && args, int flags, - std::false_type /* is void */) -{ - using args_type = callable_traits::args_t<decltype(&Func::step)>; - using span_type = typename std::tuple_element<1U, args_type>::type; - using func_type = typename std::decay<Func>::type; - using func_args_type = typename std::decay<Args>::type; - - return sqlite3_create_window_function( - db, name.c_str(), - span_type::extent == boost::dynamic_extent ? -1 : static_cast<int>(span_type::extent), - SQLITE_UTF8 | flags, - new (memory_tag{}) func_args_type(std::forward<Args>(args)), - +[](sqlite3_context* ctx, int len, sqlite3_value** args) noexcept //xStep - { - auto aa = reinterpret_cast<value*>(args); - auto fa = reinterpret_cast<func_args_type*>(sqlite3_user_data(ctx)); - auto c = static_cast<func_type*>(sqlite3_aggregate_context(ctx, 0)); - - execute_context_function( - ctx, - [&]() -> result<decltype(c->step(span_type{aa, static_cast<std::size_t>(len)}))> - { - if (c == nullptr) - { - auto p = sqlite3_aggregate_context(ctx, sizeof(func_type)); - if (!p) - return {system::in_place_error, error(SQLITE_NOMEM)}; - c = mp11::tuple_apply(window_function_maker<func_type>{p}, *fa); - } - return c->step(span_type{aa, static_cast<std::size_t>(len)}); - }); - - }, - [](sqlite3_context* ctx) // xFinal - { - auto fa = reinterpret_cast<func_args_type*>(sqlite3_user_data(ctx)); - auto c = static_cast<func_type*>(sqlite3_aggregate_context(ctx, 0)); - execute_context_function( - ctx, - [&]() -> result<decltype(c->value())> - { - if (c == nullptr) - { - auto p = sqlite3_aggregate_context(ctx, sizeof(func_type)); - if (!p) - return {system::in_place_error, error(SQLITE_NOMEM)}; - c = mp11::tuple_apply(window_function_maker<func_type>{p}, *fa); - } - - struct reaper {void operator()(func_type * c) { c->~func_type();}}; - std::unique_ptr<func_type, reaper> cl{c}; - return c->value(); - }); - }, - [](sqlite3_context* ctx) //xValue - { - auto fa = reinterpret_cast<func_args_type*>(sqlite3_user_data(ctx)); - auto c = static_cast<func_type*>(sqlite3_aggregate_context(ctx, 0)); - execute_context_function( - ctx, - [&]() -> result<decltype(c->value())> - { - if (c == nullptr) - { - auto p = sqlite3_aggregate_context(ctx, sizeof(func_type)); - if (!p) - return {system::in_place_error, error(SQLITE_NOMEM)}; - c = mp11::tuple_apply(window_function_maker<func_type>{p}, *fa); - } - return c->value(); - }); - - }, - +[](sqlite3_context* ctx, int len, sqlite3_value** args) // xInverse - { - auto aa = reinterpret_cast<value*>(args); - auto fa = reinterpret_cast<func_args_type*>(sqlite3_user_data(ctx)); - auto c = static_cast<func_type*>(sqlite3_aggregate_context(ctx, 0)); - execute_context_function( - ctx, - [&]() -> result<decltype(c->inverse(span_type{aa, static_cast<std::size_t>(len)}))> - { - if (c == nullptr) - { - auto p = sqlite3_aggregate_context(ctx, sizeof(func_type)); - if (!p) - return {system::in_place_error, error(SQLITE_NOMEM)}; - c = mp11::tuple_apply(window_function_maker<func_type>{p}, *fa); - } - return c->inverse(span_type{aa, static_cast<std::size_t>(len)}); - }); - - }, - [](void * ptr) /* xDestroy */ { delete_(static_cast<func_type*>(ptr));} - ); -} - - -} - -BOOST_SQLITE_END_NAMESPACE -#endif // SQLITE_VERSION -#endif //BOOST_SQLITE_IMPL_WINDOW_FUNCTION_HPP |