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_(InvalidOid) {}
19 oid(::Oid oid) : oid_(oid) {}
20 oid(oid &oid) : oid_(oid.oid_) {}
21 oid(const oid &oid) : oid_(oid.oid_) {}
22
23 bool operator==(const oid &rhs) const { return oid_ == rhs.oid_; }
24 bool operator!=(const oid &rhs) const { return !(rhs == *this); }
25
26 bool operator==(const ::Oid &rhs) const { return oid_ == rhs; }
27 bool operator!=(const ::Oid &rhs) const { return oid_ != rhs; }
28
29 operator ::Oid() const { return oid_; }
30 operator ::Oid &() { return oid_; }
31
32 bool is_valid() const { return oid_ != InvalidOid; }
33
34private:
35 ::Oid oid_;
36};
37static_assert(sizeof(::Oid) == sizeof(oid));
38
39struct datum {
40 template <typename T, typename> friend struct datum_conversion;
41
42 operator const ::Datum &() const { return _datum; }
43
44 operator Pointer() const { return reinterpret_cast<Pointer>(_datum); }
45
46 datum() : _datum(0) {}
47 explicit datum(::Datum datum) : _datum(datum) {}
48
49 bool operator==(const datum &other) const { return _datum == other._datum; }
50
51private:
52 ::Datum _datum;
53 friend struct nullable_datum;
54};
55
56class null_datum_exception : public std::exception {
57 const char *what() const noexcept override { return "passed datum is null"; }
58};
59
61
62 bool is_null() const noexcept { return _ndatum.isnull; }
63
64 operator struct datum &() {
65 if (_ndatum.isnull) {
67 }
68 return _datum;
69 }
70
71 operator const ::Datum &() {
72 if (_ndatum.isnull) {
74 }
75 return _datum.operator const ::Datum &();
76 }
77
78 operator const struct datum &() const {
79 if (_ndatum.isnull) {
81 }
82 return _datum;
83 }
84
85 explicit nullable_datum(::NullableDatum d) : _ndatum(d) {}
86
87 explicit nullable_datum() : _ndatum({.isnull = true}) {}
88
89 explicit nullable_datum(::Datum d) : _ndatum({.value = d, .isnull = false}) {}
90 explicit nullable_datum(datum d) : _ndatum({.value = d._datum, .isnull = false}) {}
91
92 bool operator==(const nullable_datum &other) const {
93 if (is_null()) {
94 return other.is_null();
95 }
96 if (other.is_null()) {
97 return is_null();
98 }
99 return _datum.operator==(other._datum);
100 }
101
102private:
103 union {
104 ::NullableDatum _ndatum;
105 datum _datum;
106 };
107};
108
114template <typename T, typename = void> struct datum_conversion {
115
122 static T from_nullable_datum(const nullable_datum &d, const oid oid,
123 std::optional<memory_context> context = std::nullopt) = delete;
124
131 static T from_datum(const datum &, const oid,
132 std::optional<memory_context> context = std::nullopt) = delete;
138 static datum into_datum(const T &d) = delete;
139
143 static nullable_datum into_nullable_datum(const T &d) = delete;
144};
145
146template <typename T, typename R = T> struct default_datum_conversion {
153 static R from_nullable_datum(const nullable_datum &d, const oid oid,
154 std::optional<memory_context> context = std::nullopt) {
155 if (d.is_null()) {
156 throw std::runtime_error(cppgres::fmt::format("datum is null and can't be coerced into {}",
157 utils::type_name<T>()));
158 }
159 return datum_conversion<T>::from_datum(d, oid, context);
160 }
161
167 }
168};
169
170template <typename T>
171concept convertible_into_datum = requires(T t) {
172 { datum_conversion<T, void>::into_datum(std::declval<T>()) } -> std::same_as<datum>;
173};
174
175template <typename T>
176concept convertible_from_datum = requires(datum d, oid oid, std::optional<memory_context> context) {
177 { datum_conversion<T, void>::from_datum(d, oid, context) } -> std::same_as<T>;
178};
179
180template <typename T> struct unsupported_type {};
181
182template <typename T>
184T from_nullable_datum(const nullable_datum &d, const oid oid,
185 std::optional<memory_context> context = std::nullopt) {
186 return datum_conversion<std::remove_cv_t<T>>::from_nullable_datum(d, oid, context);
187}
188
189template <typename T> nullable_datum into_nullable_datum(const std::optional<T> &v) {
190 if (v.has_value()) {
191 return nullable_datum(datum_conversion<T>::into_datum(v.value()));
192 } else {
193 return nullable_datum();
194 }
195}
196
197template <typename T> nullable_datum into_nullable_datum(const T &v) {
198 if constexpr (std::same_as<nullable_datum, T>) {
199 return v;
200 }
202}
203
204template <typename T>
206 {
207 cppgres::from_nullable_datum<T>(std::declval<nullable_datum>(), std::declval<oid>(),
208 std::declval<std::optional<memory_context>>())
209 } -> std::same_as<T>;
210};
211
212template <typename T>
214 { cppgres::into_nullable_datum(std::declval<T>()) } -> std::same_as<nullable_datum>;
215};
216
217template <typename T> struct all_from_nullable_datum {
218private:
219 static constexpr std::size_t N = utils::tuple_size_v<T>;
220
221 template <std::size_t... I> static constexpr bool impl(std::index_sequence<I...>) {
222 return (
223 ... &&
224 convertible_from_nullable_datum<utils::remove_optional_t<utils::tuple_element_t<I, T>>>);
225 }
226
227public:
228 static constexpr bool value = impl(std::make_index_sequence<N>{});
229};
230
231} // namespace cppgres
Definition: datum.hpp:56
Definition: datum.hpp:176
Definition: datum.hpp:171
Definition: datum.hpp:217
A trait to convert from and into a cppgres::datum.
Definition: datum.hpp:114
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:39
Definition: datum.hpp:146
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:153
static nullable_datum into_nullable_datum(const T &d)
Convert into a nullable datum.
Definition: datum.hpp:165
Definition: datum.hpp:60
Definition: datum.hpp:17
Definition: datum.hpp:180
Definition: value.hpp:8