12template <
class T,
class... Args>
14 { t.update(args...) };
17template <
class T,
class... Args>
22template <
class T,
class... Args>
24 { t.serialize() } -> std::same_as<bytea>;
25 { T(ba) } -> std::same_as<T>;
36template <
class T,
class... Args>
38 { T(t, t1) } -> std::same_as<T>;
41template <
class Agg,
typename... InTs>
datum aggregate_sfunc(
value state, InTs... args) {
44 if (!
ffi_guard{::AggCheckCallContext}(current_postgres_function::call_info().operator*(),
46 report(ERROR,
"not aggregate context");
49 if constexpr (!convertible_into_datum<Agg> && finalizable_aggregate<Agg, InTs...>) {
51 if (state.get_nullable_datum().is_null()) {
52 state0 = memory_context(aggctx).construct<Agg>();
54 state0 =
reinterpret_cast<Agg *
>(
55 from_nullable_datum<void *>(state.get_nullable_datum(), state.get_type().oid));
58 state0->update(args...);
61 }
else if constexpr (convertible_into_datum<Agg>) {
63 state0.update(args...);
66 report(ERROR,
"not supported");
67 __builtin_unreachable();
70template <
class Agg,
typename... InTs> nullable_datum aggregate_ffunc(value state) {
71 if constexpr (finalizable_aggregate<Agg, InTs...>) {
73 if (state.get_nullable_datum().is_null()) {
74 state0 = memory_context().construct<Agg>();
76 state0 =
reinterpret_cast<Agg *
>(
77 from_nullable_datum<void *>(state.get_nullable_datum(), state.get_type().oid));
79 return into_nullable_datum(state0->finalize());
81 report(ERROR,
"this aggregate does not support final function");
82 __builtin_unreachable();
86template <
class Agg,
typename... InTs> bytea aggregate_serial(value state) {
87 if constexpr (serializable_aggregate<Agg, InTs...>) {
88 if (state.get_type().oid == INTERNALOID) {
90 state0 =
reinterpret_cast<Agg *
>(
91 from_nullable_datum<void *>(state.get_nullable_datum(), state.get_type().oid));
92 bytea ba = state0->serialize();
96 report(ERROR,
"this aggregate does not support serialize");
97 __builtin_unreachable();
100template <
class Agg,
typename... InTs> datum aggregate_deserial(bytea ba, value) {
101 if constexpr (serializable_aggregate<Agg, InTs...>) {
102 MemoryContext aggctx;
103 if (!ffi_guard{::AggCheckCallContext}(current_postgres_function::call_info().operator*(),
105 report(ERROR,
"not aggregate context");
107 Agg *state0 = memory_context(aggctx).construct<Agg>(ba);
110 report(ERROR,
"this aggregate does not support serialize");
111 __builtin_unreachable();
114template <
class Agg,
typename... InTs> datum aggregate_combine(value state, value other) {
115 static_assert(!(std::is_constructible_v<Agg, Agg &, Agg &> &&
116 !std::is_constructible_v<Agg, const Agg &, const Agg &>),
117 "combining constructor must take const references: both operands remain owned by "
118 "the aggregate memory context and are destroyed when it is reset");
119 MemoryContext aggctx;
120 if (!ffi_guard{::AggCheckCallContext}(current_postgres_function::call_info().operator*(),
122 report(ERROR,
"not aggregate context");
124 if constexpr (combinable_aggregate<Agg, InTs...>) {
125 if constexpr (!convertible_into_datum<Agg> && finalizable_aggregate<Agg, InTs...>) {
127 if (state.get_nullable_datum().is_null()) {
128 state0 = memory_context(aggctx).construct<Agg>();
130 state0 =
reinterpret_cast<Agg *
>(
131 from_nullable_datum<void *>(state.get_nullable_datum(), state.get_type().oid));
135 if (other.get_nullable_datum().is_null()) {
136 state1 = memory_context(aggctx).construct<Agg>();
138 state1 =
reinterpret_cast<Agg *
>(
139 from_nullable_datum<void *>(other.get_nullable_datum(), other.get_type().oid));
143 memory_context(aggctx).construct<Agg>(std::as_const(*state0), std::as_const(*state1));
146 }
else if constexpr (convertible_into_datum<Agg>) {
152 report(ERROR,
"not supported");
153 __builtin_unreachable();
158#define declare_aggregate(name, typname, ...) \
159 static_assert(::cppgres::aggregate<typname, ##__VA_ARGS__>); \
160 static_assert(::cppgres::convertible_into_datum<typname> || \
161 ::cppgres::finalizable_aggregate<typname, ##__VA_ARGS__>, \
162 "must be convertible to datum or have finalize()"); \
163 postgres_function(name##_sfunc, (cppgres::aggregate_sfunc<typname, ##__VA_ARGS__>)); \
164 postgres_function(name##_ffunc, (cppgres::aggregate_ffunc<typname, ##__VA_ARGS__>)); \
165 postgres_function(name##_serial, (cppgres::aggregate_serial<typname, ##__VA_ARGS__>)); \
166 postgres_function(name##_deserial, (cppgres::aggregate_deserial<typname, ##__VA_ARGS__>)); \
167 postgres_function(name##_combine, (cppgres::aggregate_combine<typname, ##__VA_ARGS__>));
Definition: aggregate.hpp:13
Aggregate state that can be combined with another instance (parallel aggregation)
Definition: aggregate.hpp:37
Definition: datum.hpp:171
Definition: aggregate.hpp:18
Definition: aggregate.hpp:23
static T from_nullable_datum(const nullable_datum &d, const oid oid, std::optional< memory_context > context=std::nullopt)=delete
Convert from a nullable datum.
static datum into_datum(const T &d)=delete
Convert datum into a type.