On Thu, Sep 10, 2026 at 3:59 PM Fujii Masao <[email protected]> wrote:
> postgres_fdw stats import seems to have several potential issues.

> (1) User-defined functions may be executed with unexpected privileges
>
> ANALYZE on a foreign table with import_stats disabled invokes
> user-defined functions (e.g., domain constraints) as the foreign table's
> owner. But, with import_stats enabled, they are invoked as the user
> running ANALYZE. So, if that user is a superuser, those functions would
> be run with superuser privileges. Could this be a security issue?

Sorry, I don't follow this.  Could you elaborate on it using an example?

> (2) COLLATE is not supported by old remote servers
>
> Stats import sends COLLATE "C" to the remote server without checking
> its version, but COLLATE is supported only in v9.1 and later.
> The comment in deparse.c explicitly mentions this compatibility issue, and
> IMPORT FOREIGN SCHEMA disables collation import for remote servers older
> than v9.1.
>
> So, it seems stats import should handle this issue as well, e.g., either by
> avoiding COLLATE or by falling back to sampling.

Good catch!  I feel like just falling back to sampling.

> (3) n_distinct is ignored
>
> Stats import ignores the foreign table column's n_distinct option, whereas
> normal ANALYZE applies it after collecting statistics.
>
> IMO, n_distinct should also be applied to imported stats.

Rather than making the code complicated for that, I feel like just
copying the remote table's stats as-proposed, as in most cases, those
stats are generated on the remote server under the correct settings of
parameters like n_distcint.  How about adding a note about that?

> (4) Imported relpages may use different block sizes
>
> Stats import stores the remote relpages value unchanged, whereas the
> normal ANALYZE uses pg_relation_size() divided by the local BLCKSZ to
> handle the case where the block sizes differ between the local and remote
> servers.
>
> We should convert the imported page count to local block units, for example?

Good point!  Actually, this is a known issue in the normal ANALYZE:

/*
 * Construct SELECT statement to acquire size in blocks of given relation.
 *
 * Note: we use local definition of block size, not remote definition.
 * This is perhaps debatable.
 *
 * Note: pg_relation_size() exists in 8.1 and later.
 */
void
deparseAnalyzeSizeSql(StringInfo buf, Relation rel)

>From a cost calculation perspective, I think it's appropriate to use
the imported relpages as-is, as it's used to estimate the cost for
remote operations, not local ones, and thus we should actually instead
fix the normal-ANALYZE handling to calculate the size based on the
remote definition of block size.

Thanks for the report!

Best regards,
Etsuro Fujita


Reply via email to