You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This pleasant Rust representation is, unfortunately, not something that Postgres meaningfully exposes. This type "exists" but purely in virtual logic, not the code: instead you get to know which variant of this you are dealing with via side-channel information. In many cases, you are presumed to already know which variant you will receive.
When we then operate on either DatumRef or DatumMut, we usually need to detoast it, which requires an operation that abstractly looks like:
In some cases, detoasting does not occur, but it is a wildly dominant case and the source of many bugs in the codebase. Data in Postgres can sometimes even require recursive detoasting, i.e. a toasted varlena may be detoasted into data that contains potentially multiple toasted varlenas that each have to be detoasted themselves. Even if this isn't the case for a given compound structure, in general the actual "leaf" type we want to interact with will sometimes require detoasting. As we want to abstract these to handle them somewhat uniformly, the core abstraction, the one which everything will build on, will need to be able to capture the gnarliest cases, so we want to correctly represent the resulting lifetimes of slices of toast.
Required Types
Some of the above example code mentions some hypothetical types. The following, however, are actually required.
Datum<'lt>
As distinct from pg_sys::Datum, henceforth known as RawDatum, this is a datum with a lifetime bound to reflect the limited lifetime of the origin before its deallocation. Copying types out without bounds remains possible, still, but most of the complicated uses of it will also require the next type:
&'mcx MemCx<'mcx>
Almost always obtained as a borrow, this is a MemoryContext, fundamentally, but it also needs lifetime bounds (and thus gets a shorter name, since there's going to be another 4~8 characters dotting every usage).
Usage of this is tricky. In some cases this may be integrated into pg_extern functions, fundamentally, by obtaining it inside the wrapping function, and then passing it in as an argument, so that the lifetime, as far as the inner Rust function can discern, can reflect the lifetime of the functions own execution. In other cases, it may revolve around closure-based usage (akin to Spi::connect but less broken).
Required Traits
Obviously, this is entirely incompatible with trait FromDatum as it currently stands, so that needs to be reworked: it doesn't have lifetime bounds, after all.
trait DetoastDatum<'dat, 'mcx>
A tentative name for the trait that can unpack data into decompressed, direct forms, containing the necessary fn detoast_datum function.
So... PR?
Unfortunately, the work to integrate these components, alone, into the codebase, is necessarily going to be absolutely massive, and this design itself is the result of discarding about half-a-dozen other designs, starting with "the codebase as-is". Thus this issue as a touchstone for "where are we?"
The text was updated successfully, but these errors were encountered:
The Lifetimes of Data in Context
When an arbitrary pointer is initially yielded from Postgres, we get what is effectively:
This pleasant Rust representation is, unfortunately, not something that Postgres meaningfully exposes. This type "exists" but purely in virtual logic, not the code: instead you get to know which variant of this you are dealing with via side-channel information. In many cases, you are presumed to already know which variant you will receive.
When we then operate on either
DatumRef
orDatumMut
, we usually need to detoast it, which requires an operation that abstractly looks like:In some cases, detoasting does not occur, but it is a wildly dominant case and the source of many bugs in the codebase. Data in Postgres can sometimes even require recursive detoasting, i.e. a toasted varlena may be detoasted into data that contains potentially multiple toasted varlenas that each have to be detoasted themselves. Even if this isn't the case for a given compound structure, in general the actual "leaf" type we want to interact with will sometimes require detoasting. As we want to abstract these to handle them somewhat uniformly, the core abstraction, the one which everything will build on, will need to be able to capture the gnarliest cases, so we want to correctly represent the resulting lifetimes of slices of toast.
Required Types
Some of the above example code mentions some hypothetical types. The following, however, are actually required.
Datum<'lt>
As distinct from
pg_sys::Datum
, henceforth known as RawDatum, this is a datum with a lifetime bound to reflect the limited lifetime of the origin before its deallocation. Copying types out without bounds remains possible, still, but most of the complicated uses of it will also require the next type:&'mcx MemCx<'mcx>
Almost always obtained as a borrow, this is a MemoryContext, fundamentally, but it also needs lifetime bounds (and thus gets a shorter name, since there's going to be another 4~8 characters dotting every usage).
Usage of this is tricky. In some cases this may be integrated into
pg_extern
functions, fundamentally, by obtaining it inside the wrapping function, and then passing it in as an argument, so that the lifetime, as far as the inner Rust function can discern, can reflect the lifetime of the functions own execution. In other cases, it may revolve around closure-based usage (akin toSpi::connect
but less broken).Required Traits
Obviously, this is entirely incompatible with
trait FromDatum
as it currently stands, so that needs to be reworked: it doesn't have lifetime bounds, after all.trait DetoastDatum<'dat, 'mcx>
A tentative name for the trait that can unpack data into decompressed, direct forms, containing the necessary
fn detoast_datum
function.So... PR?
Unfortunately, the work to integrate these components, alone, into the codebase, is necessarily going to be absolutely massive, and this design itself is the result of discarding about half-a-dozen other designs, starting with "the codebase as-is". Thus this issue as a touchstone for "where are we?"
The text was updated successfully, but these errors were encountered: