5#ifndef BOOST_SQLITE_IMPL_WINDOW_FUNCTION_HPP
6#define BOOST_SQLITE_IMPL_WINDOW_FUNCTION_HPP
7#if SQLITE_VERSION_NUMBER >= 3025000
9#include <boost/sqlite/detail/config.hpp>
10#include <boost/sqlite/cstring_ref.hpp>
11#include <boost/sqlite/memory.hpp>
12#include <boost/sqlite/result.hpp>
13#include <boost/sqlite/value.hpp>
15BOOST_SQLITE_BEGIN_NAMESPACE
20template<
typename Func>
21int create_window_function(sqlite3 * db, cstring_ref name, Func && func,
24 using args_type = callable_traits::args_t<
decltype(&Func::step)>;
25 using context_type =
typename std::remove_reference<typename std::tuple_element<1u, args_type>::type>::type;
26 using span_type =
typename std::tuple_element<2U, args_type>::type;
27 using func_type =
typename std::decay<Func>::type;
29 return sqlite3_create_window_function(
31 span_type::extent == boost::dynamic_extent ? -1 : static_cast<int>(span_type::extent),
33 new (memory_tag{}) func_type(std::forward<Func>(func)),
34 +[](sqlite3_context* ctx, int len, sqlite3_value** args) noexcept
36 auto aa =
reinterpret_cast<value*
>(args);
37 auto f =
reinterpret_cast<Func*
>(sqlite3_user_data(ctx));
38 auto c =
static_cast<context_type*
>(sqlite3_aggregate_context(ctx, 0));
40 execute_context_function(
46 auto p = sqlite3_aggregate_context(ctx,
sizeof(context_type));
48 return error(SQLITE_NOMEM);
49 c =
new (p) context_type();
51 f->step(*c, span_type{aa,
static_cast<std::size_t
>(len)});
56 [](sqlite3_context* ctx)
58 auto f =
reinterpret_cast<Func*
>(sqlite3_user_data(ctx));
59 auto c =
static_cast<context_type*
>(sqlite3_aggregate_context(ctx, 0));
60 execute_context_function(
62 [&]() -> result<
decltype(f->value(*c))>
66 auto p = sqlite3_aggregate_context(ctx, sizeof(context_type));
68 return error(SQLITE_NOMEM);
69 c = new (p) context_type();
71 struct reaper {void operator()(context_type * c) { c->~context_type();}};
72 std::unique_ptr<context_type, reaper> cl{c};
77 [](sqlite3_context* ctx)
79 auto f =
reinterpret_cast<Func*
>(sqlite3_user_data(ctx));
80 auto c =
static_cast<context_type*
>(sqlite3_aggregate_context(ctx, 0));
81 execute_context_function(
83 [&]() -> result<
decltype(f->value(*c))>
87 auto p = sqlite3_aggregate_context(ctx, sizeof(context_type));
89 return error(SQLITE_NOMEM);
90 c = new (p) context_type();
96 +[](sqlite3_context* ctx,
int len, sqlite3_value** args)
98 auto aa =
reinterpret_cast<value*
>(args);
99 auto f =
reinterpret_cast<Func*
>(sqlite3_user_data(ctx));
100 auto c =
static_cast<context_type*
>(sqlite3_aggregate_context(ctx, 0));
101 execute_context_function(
103 [&]() -> result<
decltype(f->inverse(*c, span_type{aa, static_cast<std::size_t>(len)}))>
107 auto p = sqlite3_aggregate_context(ctx, sizeof(context_type));
109 return error(SQLITE_NOMEM);
110 c = new (p) context_type();
112 f->inverse(*c, span_type{aa, static_cast<std::size_t>(len)});
117 [](
void * ptr) { delete_(
static_cast<func_type*
>(ptr));}
121template<
typename Func>
122int create_window_function(sqlite3 * db, cstring_ref name, Func && func,
125 using args_type = callable_traits::args_t<
decltype(&Func::step)>;
126 using context_type =
typename std::remove_reference<typename std::tuple_element<1u, args_type>::type>::type;
127 using span_type =
typename std::tuple_element<2U, args_type>::type;
128 using func_type =
typename std::decay<Func>::type;
130 return sqlite3_create_window_function(
132 span_type::extent == boost::dynamic_extent ? -1 : static_cast<int>(span_type::extent),
134 new (memory_tag{}) func_type(std::forward<Func>(func)),
135 +[](sqlite3_context* ctx, int len, sqlite3_value** args) noexcept
137 auto aa =
reinterpret_cast<value*
>(args);
138 auto f =
reinterpret_cast<Func*
>(sqlite3_user_data(ctx));
139 auto c =
static_cast<context_type*
>(sqlite3_aggregate_context(ctx, 0));
141 execute_context_function(
143 [&]() -> result<
decltype(f->step(*c, span_type{aa, static_cast<std::size_t>(len)}))>
147 auto p = sqlite3_aggregate_context(ctx, sizeof(context_type));
149 return error(SQLITE_NOMEM);
150 c = new (p) context_type();
152 return f->step(*c, span_type{aa, static_cast<std::size_t>(len)});
156 [](sqlite3_context* ctx)
158 auto f =
reinterpret_cast<Func*
>(sqlite3_user_data(ctx));
159 auto c =
static_cast<context_type*
>(sqlite3_aggregate_context(ctx, 0));
160 execute_context_function(
162 [&]() -> result<
decltype(f->value(*c))>
166 auto p = sqlite3_aggregate_context(ctx, sizeof(context_type));
168 return error(SQLITE_NOMEM);
169 c = new (p) context_type();
172 struct reaper {void operator()(context_type * c) { c->~context_type();}};
173 std::unique_ptr<context_type, reaper> cl{c};
177 [](sqlite3_context* ctx)
179 auto f =
reinterpret_cast<Func*
>(sqlite3_user_data(ctx));
180 auto c =
static_cast<context_type*
>(sqlite3_aggregate_context(ctx, 0));
181 execute_context_function(
183 [&]() -> result<
decltype(f->value(*c))>
187 auto p = sqlite3_aggregate_context(ctx, sizeof(context_type));
189 return error(SQLITE_NOMEM);
190 c = new (p) context_type();
196 +[](sqlite3_context* ctx,
int len, sqlite3_value** args)
198 auto aa =
reinterpret_cast<value*
>(args);
199 auto f =
reinterpret_cast<Func*
>(sqlite3_user_data(ctx));
200 auto c =
static_cast<context_type*
>(sqlite3_aggregate_context(ctx, 0));
201 execute_context_function(
203 [&]() -> result<
decltype(f->inverse(*c, span_type{aa, static_cast<std::size_t>(len)}))>
207 auto p = sqlite3_aggregate_context(ctx, sizeof(context_type));
209 return error(SQLITE_NOMEM);
210 c = new (p) context_type();
212 return f->inverse(*c, span_type{aa, static_cast<std::size_t>(len)});
216 [](
void * ptr) { delete_(
static_cast<func_type*
>(ptr));}
223BOOST_SQLITE_END_NAMESPACE