32 std::string_view
name(
bool qualified =
false) {
33 if (!OidIsValid(
oid)) {
34 throw std::runtime_error(
"invalid type");
36 return (qualified ?
ffi_guard{::format_type_be_qualified}
40 bool operator==(
const type &other)
const {
return oid == other.oid; }
46 bool is(
const type &t) {
return false; }
47 type type_for() =
delete;
52 { type_traits<T>().type_for() } -> std::same_as<type>;
53 { type_traits<T>().is(t) } -> std::same_as<bool>;
56template <
typename T>
requires std::is_reference_v<T>
59 type_traits(
const T &) {}
60 constexpr type type_for() {
return type_traits<std::remove_reference_t<T>>().type_for(); }
80 : value_datum(other.value_datum), ctx(other.ctx) {}
82 : value_datum(std::move(other.value_datum)), ctx(std::move(other.ctx)) {}
84 value_datum = std::move(other.value_datum);
85 ctx = std::move(other.ctx);
89 memory_context &get_memory_context() {
return ctx.get_memory_context(); }
91 datum get_datum()
const {
return value_datum; }
96 void *ptr(
bool tracked =
true)
const {
97 if (tracked && ctx.resets() > 0) {
100 return reinterpret_cast<void *
>(value_datum.operator const ::Datum &());
104static_assert(std::copy_constructible<non_by_value_type>);
107 using non_by_value_type::non_by_value_type;
109 operator void *() {
return VARDATA_ANY(detoasted_ptr()); }
111 datum get_datum()
const {
return value_datum; }
113 bool is_detoasted()
const {
return detoasted !=
nullptr; }
116 void *detoasted =
nullptr;
117 std::optional<tracking_memory_context<memory_context>> detoasted_ctx;
118 void *detoasted_ptr() {
119 if (detoasted !=
nullptr) {
120 if (detoasted_ctx.has_value() && detoasted_ctx->resets() > 0) {
125 auto *source =
reinterpret_cast<::
varlena *
>(ptr());
126 detoasted =
ffi_guard{::pg_detoast_datum}(source);
127 if (detoasted == source) {
137 using varlena::varlena;
139 operator std::string_view() {
140 return {
static_cast<char *
>(this->
operator void *()), VARSIZE_ANY_EXHDR(this->detoasted_ptr())};
144using byte_array = std::span<const std::byte>;
147 using varlena::varlena;
151 auto alloc = ctx.alloc<std::byte>(VARHDRSZ + ba.size_bytes());
152 SET_VARSIZE(alloc, VARHDRSZ + ba.size_bytes());
153 auto ptr = VARDATA_ANY(alloc);
154 std::copy(ba.begin(), ba.end(),
reinterpret_cast<std::byte *
>(ptr));
155 return datum(PointerGetDatum(alloc));
159 operator byte_array() {
160 return {
reinterpret_cast<std::byte *
>(this->
operator void *()),
161 VARSIZE_ANY_EXHDR(this->detoasted_ptr())};
167 { T::type() } -> std::same_as<type>;
168 { t.flat_size() } -> std::same_as<std::size_t>;
169 { t.flatten_into(span) };
170 { T::restore_from(span) } -> std::same_as<T>;
174 using flattenable_type = T;
175 using varlena::varlena;
178 :
varlena(allocate_expanded()),
179 detoasted_value(
reinterpret_cast<expanded *
>(DatumGetPointer(value_datum))) {}
181 template <
typename... Args>
184 requires(
sizeof...(Args) > 0 &&
185 !(
sizeof...(Args) == 1 &&
186 std::is_same_v<std::decay_t<std::tuple_element_t<0, std::tuple<Args...>>>,
188 :
varlena(allocate_expanded(args...)),
189 detoasted_value(
reinterpret_cast<expanded *
>(DatumGetPointer(value_datum))) {}
192 if (detoasted_value.has_value()) {
193 return detoasted_value.value()->inner;
195 if (VARATT_IS_EXTERNAL_EXPANDED(ptr())) {
196 detoasted_value =
reinterpret_cast<expanded *
>(DatumGetEOHP(value_datum));
197 return detoasted_value.value()->inner;
199 auto *ptr1 =
reinterpret_cast<std::byte *
>(varlena::operator
void *());
201 auto *
value =
new (ctx.alloc<expanded>())
202 expanded(T::restore_from(std::span(ptr1, VARSIZE_ANY_EXHDR(detoasted_ptr()))));
203 ctx.register_reset_callback(
205 auto v =
reinterpret_cast<expanded *
>(arg);
209 init(&
value->hdr, ctx);
210 detoasted_value =
value;
215 datum get_expanded_datum()
const {
216 if (!detoasted_value.has_value()) {
217 throw std::runtime_error(
"hasn't been expanded yet");
219 return datum(EOHPGetRWDatum(&detoasted_value.value()->hdr));
224 expanded(
auto &&...args) : inner(std::forward<
decltype(args)...>(args)...) {}
225 ::ExpandedObjectHeader hdr;
229 template <
typename... Args>
static auto allocate_expanded(Args &&...args) {
232 auto *e = ctx.construct<expanded>(args...);
234 return std::make_pair(
datum(PointerGetDatum(e)), ctx);
238 std::optional<expanded *> detoasted_value = std::nullopt;
240 static void init(ExpandedObjectHeader *hdr,
memory_context &ctx) {
241 using header = int32_t;
243 static const ::ExpandedObjectMethods eom = {
245 [](ExpandedObjectHeader *eohptr) {
246 auto *e =
reinterpret_cast<expanded *
>(eohptr);
247 T *inner = &e->inner;
248 return inner->flat_size() +
sizeof(header);
251 [](ExpandedObjectHeader *eohptr,
void *result,
size_t allocated_size) {
252 auto *e =
reinterpret_cast<expanded *
>(eohptr);
253 T *inner = &e->inner;
254 SET_VARSIZE(
reinterpret_cast<header *
>(result), allocated_size);
255 auto bytes =
reinterpret_cast<std::byte *
>(result) +
sizeof(header);
256 std::span buffer(bytes, allocated_size -
sizeof(header));
257 inner->flatten_into(buffer);
260 ffi_guard{::EOH_init_header}(hdr, &eom, ctx);
269 { t.type_for() } -> std::same_as<type>;
Definition: memory.hpp:172
Definition: memory.hpp:139
Definition: memory.hpp:326
Definition: memory.hpp:189
Postgres type.
Definition: type.hpp:22
std::string_view name(bool qualified=false)
Type name as defined in Postgres.
Definition: type.hpp:32