]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
postgres_fdw: Fix deparsing of remote column names in stats import.
authorEtsuro Fujita <efujita@postgresql.org>
Thu, 14 May 2026 08:05:00 +0000 (17:05 +0900)
committerEtsuro Fujita <efujita@postgresql.org>
Thu, 14 May 2026 08:05:00 +0000 (17:05 +0900)
build_remattrmap() deparses a list of remote column names for a query
that retrieves attribute stats for them from the remote server.
Previously, it did so by using the array-literal syntax with each column
name individually quoted by quote_identifier(), causing the query to
fail on the remote server with a syntax error or no results when that
column name included a single quote or backslash, as quote_identifier()
doesn't escape those characters, making the query invalid or incorrect.
Fix by switching from the array-literal syntax to the ARRAY constructor
syntax with each column name individually quoted by
deparseStringLiteral().

Oversight in commit 28972b6fc.

Reported-by: Satya Narlapuram <satyanarlapuram@gmail.com>
Reported-by: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Author: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Reviewed-by: Alex Guo <guo.alex.hengchen@gmail.com>
Reviewed-by: Zhenwei Shang <a934172442@gmail.com>
Reviewed-by: Etsuro Fujita <etsuro.fujita@gmail.com>
Discussion: https://postgr.es/m/CAHg%2BQDc9%3DWtYi%3DJW6QUL6ASOJc6PcGPTuxoMkhnkQ7oi7j5atg%40mail.gmail.com
Discussion: https://postgr.es/m/CAJTYsWWGhVDFjr%2BsmdYdU-Q_TT9YMzXA4QcLCr7rizDOyrEEow%40mail.gmail.com

contrib/postgres_fdw/expected/postgres_fdw.out
contrib/postgres_fdw/postgres_fdw.c
contrib/postgres_fdw/sql/postgres_fdw.sql

index aaffcf31271924612d788bcecddf6eabc1233071..e90289e4ab12eaba1fb044246b2b319af4af559c 100644 (file)
@@ -12917,11 +12917,23 @@ CREATE FOREIGN TABLE simport_fview (c1 int, c2 text)
 ALTER FOREIGN TABLE simport_fview OPTIONS (ADD restore_stats 'true');
 ANALYZE simport_fview;                    -- should fail
 WARNING:  could not import statistics for foreign table "public.simport_fview" --- remote table "public.simport_view" is of relkind "v" which cannot have statistics
+-- This tests build_remattrmap()'s deparsing of column names that include
+-- single quotes or backslashes
+CREATE TABLE dtest_table ("col'quote" int, "col\backslash" int);
+CREATE FOREIGN TABLE dtest_ftable ("col'quote" int, "col\backslash" int)
+       SERVER loopback OPTIONS (table_name 'dtest_table', restore_stats 'true');
+INSERT INTO dtest_table SELECT g, g FROM generate_series(1, 10) g;
+ANALYZE dtest_table;
+ANALYZE VERBOSE dtest_ftable;             -- should work
+INFO:  importing statistics for foreign table "public.dtest_ftable"
+INFO:  finished importing statistics for foreign table "public.dtest_ftable"
 -- cleanup
 DROP FOREIGN TABLE simport_ftable;
 DROP FOREIGN TABLE simport_fview;
 DROP VIEW simport_view;
 DROP TABLE simport_table;
+DROP FOREIGN TABLE dtest_ftable;
+DROP TABLE dtest_table;
 -- ===================================================================
 -- test for postgres_fdw_get_connections function with check_conn = true
 -- ===================================================================
index 0657618eda3960f4f80bb967708a3760299d5924..85be46eb2a2de793e0fd91e6a1191df3a3375f14 100644 (file)
@@ -5886,7 +5886,7 @@ fetch_attstats(PGconn *conn, int server_version_num,
                                                   " AND tablename = ");
        deparseStringLiteral(&sql, remote_relname);
        appendStringInfo(&sql,
-                                        " AND attname = ANY('%s'::text[])",
+                                        " AND attname = ANY(%s)",
                                         column_list);
 
        /* inherited is supported since Postgres 9.0 */
@@ -5921,7 +5921,7 @@ build_remattrmap(Relation relation, List *va_cols,
 
        remattrmap = palloc_array(RemoteAttributeMapping, tupdesc->natts);
        initStringInfo(column_list);
-       appendStringInfoChar(column_list, '{');
+       appendStringInfoString(column_list, "ARRAY[");
        for (int i = 0; i < tupdesc->natts; i++)
        {
                Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
@@ -5954,7 +5954,7 @@ build_remattrmap(Relation relation, List *va_cols,
 
                if (attrcnt > 0)
                        appendStringInfoString(column_list, ", ");
-               appendStringInfoString(column_list, quote_identifier(remote_attname));
+               deparseStringLiteral(column_list, remote_attname);
 
                remattrmap[attrcnt].local_attnum = attnum;
                strncpy(remattrmap[attrcnt].local_attname, attname, NAMEDATALEN);
@@ -5962,7 +5962,7 @@ build_remattrmap(Relation relation, List *va_cols,
                remattrmap[attrcnt].res_index = -1;
                attrcnt++;
        }
-       appendStringInfoChar(column_list, '}');
+       appendStringInfoChar(column_list, ']');
 
        /* Sort mapping by remote attribute name if needed. */
        if (attrcnt > 1)
index 267d3c1a7e7a70002c1ae7910e4576dd65e8adda..dfc58beb0d2c32b2de3ff764e0de73477baa0630 100644 (file)
@@ -4573,11 +4573,24 @@ ALTER FOREIGN TABLE simport_fview OPTIONS (ADD restore_stats 'true');
 
 ANALYZE simport_fview;                    -- should fail
 
+-- This tests build_remattrmap()'s deparsing of column names that include
+-- single quotes or backslashes
+CREATE TABLE dtest_table ("col'quote" int, "col\backslash" int);
+CREATE FOREIGN TABLE dtest_ftable ("col'quote" int, "col\backslash" int)
+       SERVER loopback OPTIONS (table_name 'dtest_table', restore_stats 'true');
+
+INSERT INTO dtest_table SELECT g, g FROM generate_series(1, 10) g;
+ANALYZE dtest_table;
+
+ANALYZE VERBOSE dtest_ftable;             -- should work
+
 -- cleanup
 DROP FOREIGN TABLE simport_ftable;
 DROP FOREIGN TABLE simport_fview;
 DROP VIEW simport_view;
 DROP TABLE simport_table;
+DROP FOREIGN TABLE dtest_ftable;
+DROP TABLE dtest_table;
 
 -- ===================================================================
 -- test for postgres_fdw_get_connections function with check_conn = true