pgcentralfoundation / pgrx

Build Postgres Extensions with Rust!
Other
3.68k stars 247 forks source link

`Srf<'current, 'multi: 'current>` is `Closure<'local, 'close: 'local>` #1489

Open workingjubilee opened 9 months ago

workingjubilee commented 9 months ago

In Postgres, there is a notion of a "set-returning function", usually spelled simply "SRF". This has two relevant memory contexts: The call's 'current memory context, and the "multi-call context".

Essentially, this is an implementation of an FnMut closure: the set-returning function encloses some state that it will gradually evaluate over successive calls, which has to last until the SRF's last evaluation, i.e. 'close or 'multi. The SRF may be called once or it may be called a million times to evaluate that state: we are not entirely sure at build time. Every time it is called it gets (as far as it knows) a new memory context to evaluate "locals" in with dynamic allocations, and then it has to return a value (which actually has 'local lifetime, I think?).

The most important element here is that state stored in that multi-call context has to have the right lifetime: FuncCallContext itself has at least that lifetime, as do its embedded pointers.

Every function that accepts FunctionCallInfo is also technically like this, because any time that the fcinfo's FmgrInfo is longer-lived than the current memory context, they should have a pointer to a memory context that can be used in a similar way. In most cases it doesn't matter, but this could affect a few other issues, e.g.

workingjubilee commented 9 months ago

Note that the "Materialize" mode, while not directly employed by pgrx, also exists, and it has different lifetimes than ValuePerCall (and is recommended if the lifetime is very transitory).

workingjubilee commented 9 months ago

Srf<Materialize<'_>> vs. Srf<ValuePerCall<'current, 'multi: 'current>>?