5#ifndef BOOST_SQLITE_DETAIL_AGGREGATE_FUNCTION_HPP
6#define BOOST_SQLITE_DETAIL_AGGREGATE_FUNCTION_HPP
8#include <boost/sqlite/detail/config.hpp>
9#include <boost/sqlite/detail/catch.hpp>
10#include <boost/sqlite/error.hpp>
11#include <boost/sqlite/cstring_ref.hpp>
12#include <boost/sqlite/memory.hpp>
13#include <boost/sqlite/result.hpp>
14#include <boost/sqlite/value.hpp>
16#include <boost/callable_traits/args.hpp>
17#include <boost/callable_traits/return_type.hpp>
18#include <boost/callable_traits/has_void_return.hpp>
19#include <boost/core/span.hpp>
22BOOST_SQLITE_BEGIN_NAMESPACE
27template<
typename Func>
28int create_aggregate_function(sqlite3 * db, cstring_ref name, Func && func,
31 using args_type = callable_traits::args_t<
decltype(&Func::step)>;
32 using context_type =
typename std::remove_reference<typename std::tuple_element<1u, args_type>::type>::type;
33 using span_type =
typename std::tuple_element<2U, args_type>::type;
34 using func_type =
typename std::decay<Func>::type;
36 return sqlite3_create_function_v2(
38 span_type::extent == boost::dynamic_extent ? -1 : static_cast<int>(span_type::extent),
40 new (memory_tag{}) func_type(std::forward<Func>(func)),
42 +[](sqlite3_context* ctx, int len, sqlite3_value** args)
44 auto aa =
reinterpret_cast<value*
>(args);
45 auto f =
reinterpret_cast<Func*
>(sqlite3_user_data(ctx));
46 auto c =
static_cast<context_type*
>(sqlite3_aggregate_context(ctx, 0));
48 execute_context_function(
54 auto p = sqlite3_aggregate_context(ctx,
sizeof(context_type));
56 return error(SQLITE_NOMEM);
57 c =
new (p) context_type();
59 f->step(*c, span_type{aa,
static_cast<std::size_t
>(len)});
63 [](sqlite3_context* ctx)
65 auto f =
reinterpret_cast<Func*
>(sqlite3_user_data(ctx));
66 auto c =
static_cast<context_type*
>(sqlite3_aggregate_context(ctx, 0));
68 execute_context_function(
70 [&]() -> result<
decltype(f->final(*c))>
74 auto p = sqlite3_aggregate_context(ctx, sizeof(context_type));
76 return error(SQLITE_NOMEM);
77 c = new (p) context_type();
79 struct reaper {void operator()(context_type * c) { c->~context_type();}};
80 std::unique_ptr<context_type, reaper> cl{c};
84 [](
void * ptr)
noexcept { delete_(
static_cast<func_type*
>(ptr));}
89template<
typename Func>
90int create_aggregate_function(sqlite3 * db, cstring_ref name, Func && func,
93 using args_type = callable_traits::args_t<
decltype(&Func::step)>;
94 using context_type =
typename std::remove_reference<typename std::tuple_element<1u, args_type>::type>::type;
95 using span_type =
typename std::tuple_element<2U, args_type>::type;
96 using func_type =
typename std::decay<Func>::type;
98 return sqlite3_create_function_v2(
100 span_type::extent == boost::dynamic_extent ? -1 : static_cast<int>(span_type::extent),
102 new (memory_tag{}) func_type(std::forward<Func>(func)),
104 +[](sqlite3_context* ctx, int len, sqlite3_value** args)
106 auto aa =
reinterpret_cast<value*
>(args);
107 auto f =
reinterpret_cast<Func*
>(sqlite3_user_data(ctx));
108 auto c =
static_cast<context_type*
>(sqlite3_aggregate_context(ctx, 0));
110 execute_context_function(
112 [&]() -> result<void>
116 auto p = sqlite3_aggregate_context(ctx,
sizeof(context_type));
118 return error(SQLITE_NOMEM);
119 c =
new (p) context_type();
121 f->step(*c, span_type{aa,
static_cast<std::size_t
>(len)});
125 [](sqlite3_context* ctx)
127 auto f =
reinterpret_cast<Func*
>(sqlite3_user_data(ctx));
128 auto c =
static_cast<context_type*
>(sqlite3_aggregate_context(ctx, 0));
130 execute_context_function(
132 [&]() -> result<
decltype(f->final(*c))>
136 auto p = sqlite3_aggregate_context(ctx, sizeof(context_type));
138 return error(SQLITE_NOMEM);
139 c = new (p) context_type();
141 struct reaper {void operator()(context_type * c) { c->~context_type();}};
142 std::unique_ptr<context_type, reaper> cl{c};
146 [](
void * ptr)
noexcept { delete_(
static_cast<func_type*
>(ptr));}
152BOOST_SQLITE_END_NAMESPACE