1
0
mirror of https://github.com/postgres/postgres.git synced 2026-10-23 13:29:09 +03:00

postgres_fdw: Disable attribute statistics import from pre-9.1 servers.

To import attribute statistics, postgres_fdw sent a query wity COLLATE
"C" to remote servers without checking their version.  Since COLLATE is
only supported since v9.1, this could break the import against older
servers; fix by modifying postgres_fdw to check their version and if
older, fall back to sampling.  (This commit still allows importing only
relation statistics from such an older server.)

Also, expand the documentation to mention that attribute statistics are
stored into the local server without applying the foreign table columns'
n_distinct option.

Oversight in commit 28972b6fc.

Reported-by: Fujii Masao <masao.fujii@gmail.com>
Reported-by: Osama Abdul Qader <osamaabdulqader.cs@gmail.com>
Author: Etsuro Fujita <etsuro.fujita@gmail.com>
Reviewed-by: Corey Huinker <corey.huinker@gmail.com>
Discussion: https://postgr.es/m/CAHGQGwH8%2BuDTwfohpck9v_9L3nwSWACbmC36JYRyqHd5xQN_OA%40mail.gmail.com
Backpatch-through: 19
This commit is contained in:
Etsuro Fujita
2026-09-14 19:00:01 +09:00
parent 9e9dc104ba
commit 3e44c8a441
2 changed files with 29 additions and 17 deletions

View File

@@ -570,6 +570,7 @@ static bool fetch_remote_statistics(Relation relation,
const char *local_schemaname,
const char *local_relname,
ForeignTable *table,
ForeignServer *server,
RemoteStatsResults *remstats,
RemoteAttributeMapping **p_remattrmap,
int *p_attrcnt);
@@ -5533,7 +5534,7 @@ postgresImportForeignStatistics(Relation relation, List *va_cols, int elevel)
starttime = GetCurrentTimestamp();
ok = fetch_remote_statistics(relation, va_cols,
schemaname, relname, table,
schemaname, relname, table, server,
&remstats, &remattrmap, &attrcnt);
if (ok)
@@ -5566,6 +5567,7 @@ fetch_remote_statistics(Relation relation,
const char *local_schemaname,
const char *local_relname,
ForeignTable *table,
ForeignServer *server,
RemoteStatsResults *remstats,
RemoteAttributeMapping **p_remattrmap,
int *p_attrcnt)
@@ -5682,6 +5684,19 @@ fetch_remote_statistics(Relation relation,
/* Try to get attribute stats if needed. */
if (attrcnt > 0)
{
/*
* The fetch_attstats query sends COLLATE "C" to the remote
* server; if it hasn't got it, fallback to sampling.
*/
if (server_version_num < 90100)
{
ereport(WARNING,
errmsg("could not import statistics for foreign table \"%s.%s\" --- foreign server \"%s\" is too old to support attribute statistics import",
local_schemaname, local_relname,
server->servername));
goto fetch_cleanup;
}
/* Fetch attribute stats. */
remstats->att = attstats = fetch_attstats(conn,
server_version_num,
@@ -5757,6 +5772,9 @@ fetch_attstats(PGconn *conn, int server_version_num,
StringInfoData sql;
PGresult *res;
/* The caller guarantees the remote server is v9.1 or later. */
Assert(server_version_num >= 90100);
initStringInfo(&sql);
appendStringInfoString(&sql,
"SELECT DISTINCT ON (attname COLLATE \"C\") attname,"
@@ -5800,18 +5818,11 @@ fetch_attstats(PGconn *conn, int server_version_num,
column_list);
/*
* inherited is supported since Postgres 9.0
*
* Note that this is okay because for now, we support the case where the
* remote table is partitioned, but not the case where it is inherited
* (see fetch_remote_statistics()).
* inherited and COLLATE are supported since Postgres 9.0 and 9.1,
* respectively.
*/
if (server_version_num >= 90000)
appendStringInfoString(&sql,
" ORDER BY attname COLLATE \"C\", inherited DESC");
else
appendStringInfoString(&sql,
" ORDER BY attname COLLATE \"C\"");
appendStringInfoString(&sql,
" ORDER BY attname COLLATE \"C\", inherited DESC");
res = pgfdw_exec_query(conn, sql.data, NULL);
if (PQresultStatus(res) != PGRES_TUPLES_OK)

View File

@@ -370,14 +370,15 @@ OPTIONS (ADD password_required 'false');
<para>
This option, which can be specified for a foreign table or a foreign
server, determines if <command>ANALYZE</command> on a foreign table
will instead attempt to fetch the existing statistics for the foreign
table on the remote server, and import those statistics directly to
the local server. If the attempt failed, statistics are collected by
row sampling on the foreign table.
will instead attempt to fetch the existing statistics for the remote
table, and import those statistics directly to the local server
(without applying the foreign table columns'
<literal>n_distinct</literal> option). If the attempt failed,
statistics are collected by row sampling on the foreign table.
This option is only useful if the remote table is one that can have
regular statistics (tables, not inherited, and materialized views).
When using this option, <emphasis>it is the user's responsibility
</emphasis> to ensure that the existing statistics for the foreign
</emphasis> to ensure that the existing statistics for the remote
table are up-to-date.
The default is <literal>false</literal>.
</para>