Cppgres
Build Postgres extensions in C++
Loading...
Searching...
No Matches
datum.hpp
Go to the documentation of this file.
1
4#pragma once
5
6#include "utils/utils.hpp"
7
8#include "imports.h"
9#include "memory.hpp"
10
11#include <cstdint>
12#include <optional>
13#include <string>
14
15namespace cppgres {
16
17struct oid {
18 oid(::Oid oid) : oid_(oid) {}
19 oid(oid &oid) : oid_(oid.oid_) {}
20
21 bool operator==(const oid &rhs) const { return oid_ == rhs.oid_; }
22 bool operator!=(const oid &rhs) const { return !(rhs == *this); }
23
24 bool operator==(const ::Oid &rhs) const { return oid_ == rhs; }
25 bool operator!=(const ::Oid &rhs) const { return oid_ != rhs; }
26
27 operator ::Oid() const { return oid_; }
28 operator ::Oid &() { return oid_; }
29
30private:
31 ::Oid oid_;
32};
33static_assert(sizeof(::Oid) == sizeof(oid));
34
35struct datum {
36 template <typename T, typename> friend struct datum_conversion;
37
38 operator const ::Datum &() const { return _datum; }
39
40 operator Pointer() const { return reinterpret_cast<Pointer>(_datum); }
41
42 datum() : _datum(0) {}
43 explicit datum(::Datum datum) : _datum(datum) {}
44
45 bool operator==(const datum &other) const { return _datum == other._datum; }
46
47private:
48 ::Datum _datum;
49 friend struct nullable_datum;
50};
51
52class null_datum_exception : public std::exception {
53 const char *what() const noexcept override { return "passed datum is null"; }
54};
55
57
58 bool is_null() const noexcept { return _ndatum.isnull; }
59
60 operator struct datum &() {
61 if (_ndatum.isnull) {
63 }
64 return _datum;
65 }
66
67 operator const ::Datum &() {
68 if (_ndatum.isnull) {
70 }
71 return _datum.operator const ::Datum &();
72 }
73
74 operator const struct datum &() const {
75 if (_ndatum.isnull) {
77 }
78 return _datum;
79 }
80
81 explicit nullable_datum(::NullableDatum d) : _ndatum(d) {}
82
83 explicit nullable_datum() : _ndatum({.isnull = true}) {}
84
85 explicit nullable_datum(::Datum d) : _ndatum({.value = d, .isnull = false}) {}
86 explicit nullable_datum(datum d) : _ndatum({.value = d._datum, .isnull = false}) {}
87
88 bool operator==(const nullable_datum &other) const {
89 if (is_null()) {
90 return other.is_null();
91 }
92 if (other.is_null()) {
93 return is_null();
94 }
95 return _datum.operator==(other._datum);
96 }
97
98private:
99 union {
100 ::NullableDatum _ndatum;
101 datum _datum;
102 };
103};
104
110template <typename T, typename = void> struct datum_conversion {
111
118 static T from_nullable_datum(const nullable_datum &d, const oid oid,
119 std::optional<memory_context> context = std::nullopt) = delete;
120
127 static T from_datum(const datum &, const oid,
128 std::optional<memory_context> context = std::nullopt) = delete;
134 static datum into_datum(const T &d) = delete;
135
139 static nullable_datum into_nullable_datum(const T &d) = delete;
140};
141
142template <typename T, typename R = T> struct default_datum_conversion {
149 static R from_nullable_datum(const nullable_datum &d, const oid oid,
150 std::optional<memory_context> context = std::nullopt) {
151 if (d.is_null()) {
152 throw std::runtime_error(cppgres::fmt::format("datum is null and can't be coerced into {}",
153 utils::type_name<T>()));
154 }
155 return datum_conversion<T>::from_datum(d, oid, context);
156 }
157
163 }
164};
165
166template <typename T>
167concept convertible_into_datum = requires(T t) {
168 { datum_conversion<T, void>::into_datum(std::declval<T>()) } -> std::same_as<datum>;
169};
170
171template <typename T>
172concept convertible_from_datum = requires(datum d, oid oid, std::optional<memory_context> context) {
173 { datum_conversion<T, void>::from_datum(d, oid, context) } -> std::same_as<T>;
174};
175
176template <typename T> struct unsupported_type {};
177
178template <typename T>
180T from_nullable_datum(const nullable_datum &d, const oid oid,
181 std::optional<memory_context> context = std::nullopt) {
182 return datum_conversion<std::remove_cv_t<T>>::from_nullable_datum(d, oid, context);
183}
184
185template <typename T> nullable_datum into_nullable_datum(const std::optional<T> &v) {
186 if (v.has_value()) {
187 return nullable_datum(datum_conversion<T>::into_datum(v.value()));
188 } else {
189 return nullable_datum();
190 }
191}
192
193template <typename T> nullable_datum into_nullable_datum(const T &v) {
194 if constexpr (std::same_as<nullable_datum, T>) {
195 return v;
196 }
198}
199
200template <typename T>
202 {
203 cppgres::from_nullable_datum<T>(std::declval<nullable_datum>(), std::declval<oid>(),
204 std::declval<std::optional<memory_context>>())
205 } -> std::same_as<T>;
206};
207
208template <typename T>
210 { cppgres::into_nullable_datum(std::declval<T>()) } -> std::same_as<nullable_datum>;
211};
212
213template <typename T> struct all_from_nullable_datum {
214private:
215 static constexpr std::size_t N = utils::tuple_size_v<T>;
216
217 template <std::size_t... I> static constexpr bool impl(std::index_sequence<I...>) {
218 return (
219 ... &&
220 convertible_from_nullable_datum<utils::remove_optional_t<utils::tuple_element_t<I, T>>>);
221 }
222
223public:
224 static constexpr bool value = impl(std::make_index_sequence<N>{});
225};
226
227} // namespace cppgres
Definition: datum.hpp:52
Definition: datum.hpp:172
Definition: datum.hpp:167
Definition: datum.hpp:213
A trait to convert from and into a cppgres::datum.
Definition: datum.hpp:110
static T from_datum(const datum &, const oid, std::optional< memory_context > context=std::nullopt)=delete
Convert from a datum.
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.
static nullable_datum into_nullable_datum(const T &d)=delete
Convert into a nullable datum.
Definition: datum.hpp:35
Definition: datum.hpp:142
static R from_nullable_datum(const nullable_datum &d, const oid oid, std::optional< memory_context > context=std::nullopt)
Convert from a nullable datum.
Definition: datum.hpp:149
static nullable_datum into_nullable_datum(const T &d)
Convert into a nullable datum.
Definition: datum.hpp:161
Definition: datum.hpp:56
Definition: datum.hpp:17
Definition: datum.hpp:176
Definition: value.hpp:8