From 681b3569278bc55b4e2bbfcf129245702616ecd9 Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tomas.vondra@postgresql.org>
Date: Thu, 5 Jan 2023 21:13:20 +0100
Subject: [PATCH 2/2] WIP: check relkind in FDW analyze

---
 contrib/postgres_fdw/deparse.c      |  2 +-
 contrib/postgres_fdw/postgres_fdw.c | 19 +++++++++++++++----
 2 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/contrib/postgres_fdw/deparse.c b/contrib/postgres_fdw/deparse.c
index 4461fb06f02..9f39d792280 100644
--- a/contrib/postgres_fdw/deparse.c
+++ b/contrib/postgres_fdw/deparse.c
@@ -2383,7 +2383,7 @@ deparseAnalyzeTuplesSql(StringInfo buf, Relation rel)
 	initStringInfo(&relname);
 	deparseRelation(&relname, rel);
 
-	appendStringInfoString(buf, "SELECT reltuples FROM pg_catalog.pg_class WHERE oid = ");
+	appendStringInfoString(buf, "SELECT reltuples, relkind FROM pg_catalog.pg_class WHERE oid = ");
 	deparseStringLiteral(buf, relname.data);
 	appendStringInfoString(buf, "::pg_catalog.regclass");
 }
diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index 65822b8a9aa..50b03067152 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -4978,7 +4978,7 @@ postgresAnalyzeForeignTable(Relation relation,
  *		Count tuples in foreign table (just get pg_class.reltuples).
  */
 static double
-postgresCountTuplesForForeignTable(Relation relation)
+postgresCountTuplesForForeignTable(Relation relation, bool *can_sample)
 {
 	ForeignTable *table;
 	UserMapping *user;
@@ -4986,6 +4986,10 @@ postgresCountTuplesForForeignTable(Relation relation)
 	StringInfoData sql;
 	PGresult   *volatile res = NULL;
 	volatile double reltuples = -1;
+	volatile char relkind = 0;
+
+	/* assume the relkind can't be sampled */
+	*can_sample = false;
 
 	/*
 	 * Get the connection to use.  We do the remote access as the table's
@@ -5008,9 +5012,10 @@ postgresCountTuplesForForeignTable(Relation relation)
 		if (PQresultStatus(res) != PGRES_TUPLES_OK)
 			pgfdw_report_error(ERROR, res, conn, false, sql.data);
 
-		if (PQntuples(res) != 1 || PQnfields(res) != 1)
+		if (PQntuples(res) != 1 || PQnfields(res) != 2)
 			elog(ERROR, "unexpected result from deparseAnalyzeTuplesSql query");
 		reltuples = strtod(PQgetvalue(res, 0, 0), NULL);
+		relkind = *(PQgetvalue(res, 0, 1));
 	}
 	PG_FINALLY();
 	{
@@ -5021,6 +5026,10 @@ postgresCountTuplesForForeignTable(Relation relation)
 
 	ReleaseConnection(conn);
 
+	*can_sample = (relkind == RELKIND_RELATION ||
+				   relkind == RELKIND_MATVIEW ||
+				   relkind == RELKIND_PARTITIONED_TABLE);
+
 	return reltuples;
 }
 
@@ -5167,13 +5176,15 @@ postgresAcquireSampleRowsFunc(Relation relation, int elevel,
 	 */
 	if (method != ANALYZE_SAMPLE_OFF)
 	{
-		reltuples = postgresCountTuplesForForeignTable(relation);
+		bool	can_sample;
+
+		reltuples = postgresCountTuplesForForeignTable(relation, &can_sample);
 
 		/*
 		 * Remote's reltuples could be 0 or -1 if the table has never been
 		 * vacuumed/analyzed.  In that case, disable sampling after all.
 		 */
-		if ((reltuples <= 0) || (targrows >= reltuples))
+		if ((!can_sample) || (reltuples <= 0) || (targrows >= reltuples))
 			method = ANALYZE_SAMPLE_OFF;
 		else
 		{
-- 
2.39.0

