On Tue, Jun 16, 2026 at 8:04 AM Etsuro Fujita <etsuro.fujita@gmail.com> wrote: > I thought it would be a good idea to use > pg_restore_attribute_stats/pg_restore_relation_stats, because future > changes in attribute/relation stats would be absorbed by these > functions, which would lower the maintenance cost of this feature.
I agree that we want to reuse code, but this isn't the right way to do it. For example, when we want to look up the OID of a relation from SQL, we can say 'whatever'::regclass::oid. But when we want to do the same thing from C, we don't construct a SELECT statement and execute it via SPI. Instead, we have functions like RangeVarGetRelidExtended() which provide access to the same underlying functionality more directly.
Another example is converting strings to integers. The user calls int4in(), which then hands off the call to pg_strtoint32_safe(), which can also be called via pg_strtoint32(). Hence, C code should prefer to use pg_strtoint32(), while SQL will go through int4in(). Both ultimately reach the underlying pg_strtoint32_safe() function, but the interfaces are different, so that we can have it be suitable both for SQL access and for C access.
This needs to work more like that. The underlying code that ingests and updates the stats should be shared, but the stuff that is specific to a FunctionCallInfo interface needs to be separated out so that we don't need to go through that when calling from C.
Back when pg_restore_attribute_stats and pg_restore_relation_stats were being converted from positional to variadic functions, there was a patchset or two (possibly un-posted, because I couldn't find it just now) where the variadic functions re-marshalled the arguments into a call to a fixed-parameter function. If that model were revived, we could have a more conventional DirectFunctonCall() interface.
Is it possible that we never built a direct function call interface to a variadic because we never needed one? Perhaps that time is now.
Obviously, even that wouldn't get us to the no-FunctionCallInfo-at-all goal, but it would get us out of the SPI situation. If we did have a non-fcinfo function API, that API would either have to pass char *params almost exclusively, or else each caller would have to do the translation or float-array strings to double[] and such, which would be a lot of work for the caller.
Would you be ok with a function like attribute_statistics_update, but purely with cstring args? Obviously the callers would have to modify their calls each time a new stat param is added, but that is seemingly preferable for you than the current situation.