@@ -4974,18 +4974,25 @@ postgresAnalyzeForeignTable(Relation relation,
4974
4974
}
4975
4975
4976
4976
/*
4977
- * postgresCountTuplesForForeignTable
4977
+ * postgresGetAnalyzeInfoForForeignTable
4978
4978
* Count tuples in foreign table (just get pg_class.reltuples).
4979
+ *
4980
+ * can_tablesample determines if the remote relation supports acquiring the
4981
+ * sample using TABLESAMPLE.
4979
4982
*/
4980
4983
static double
4981
- postgresCountTuplesForForeignTable (Relation relation )
4984
+ postgresGetAnalyzeInfoForForeignTable (Relation relation , bool * can_tablesample )
4982
4985
{
4983
4986
ForeignTable * table ;
4984
4987
UserMapping * user ;
4985
4988
PGconn * conn ;
4986
4989
StringInfoData sql ;
4987
4990
PGresult * volatile res = NULL ;
4988
4991
volatile double reltuples = -1 ;
4992
+ volatile char relkind = 0 ;
4993
+
4994
+ /* assume the remote relation does not support TABLESAMPLE */
4995
+ * can_tablesample = false;
4989
4996
4990
4997
/*
4991
4998
* Get the connection to use. We do the remote access as the table's
@@ -4999,7 +5006,7 @@ postgresCountTuplesForForeignTable(Relation relation)
4999
5006
* Construct command to get page count for relation.
5000
5007
*/
5001
5008
initStringInfo (& sql );
5002
- deparseAnalyzeTuplesSql (& sql , relation );
5009
+ deparseAnalyzeInfoSql (& sql , relation );
5003
5010
5004
5011
/* In what follows, do not risk leaking any PGresults. */
5005
5012
PG_TRY ();
@@ -5008,9 +5015,10 @@ postgresCountTuplesForForeignTable(Relation relation)
5008
5015
if (PQresultStatus (res ) != PGRES_TUPLES_OK )
5009
5016
pgfdw_report_error (ERROR , res , conn , false, sql .data );
5010
5017
5011
- if (PQntuples (res ) != 1 || PQnfields (res ) != 1 )
5018
+ if (PQntuples (res ) != 1 || PQnfields (res ) != 2 )
5012
5019
elog (ERROR , "unexpected result from deparseAnalyzeTuplesSql query" );
5013
5020
reltuples = strtod (PQgetvalue (res , 0 , 0 ), NULL );
5021
+ relkind = * (PQgetvalue (res , 0 , 1 ));
5014
5022
}
5015
5023
PG_FINALLY ();
5016
5024
{
@@ -5021,6 +5029,11 @@ postgresCountTuplesForForeignTable(Relation relation)
5021
5029
5022
5030
ReleaseConnection (conn );
5023
5031
5032
+ /* TABLESAMPLE is supported only for regular tables and matviews */
5033
+ * can_tablesample = (relkind == RELKIND_RELATION ||
5034
+ relkind == RELKIND_MATVIEW ||
5035
+ relkind == RELKIND_PARTITIONED_TABLE );
5036
+
5024
5037
return reltuples ;
5025
5038
}
5026
5039
@@ -5147,27 +5160,25 @@ postgresAcquireSampleRowsFunc(Relation relation, int elevel,
5147
5160
(errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
5148
5161
errmsg ("remote server does not support TABLESAMPLE feature" )));
5149
5162
5150
- /*
5151
- * For "auto" method, pick the one we believe is best. For servers with
5152
- * TABLESAMPLE support we pick BERNOULLI, for old servers we fall-back to
5153
- * random() to at least reduce network transfer.
5154
- */
5155
- if (method == ANALYZE_SAMPLE_AUTO )
5156
- {
5157
- if (server_version_num < 95000 )
5158
- method = ANALYZE_SAMPLE_RANDOM ;
5159
- else
5160
- method = ANALYZE_SAMPLE_BERNOULLI ;
5161
- }
5162
-
5163
5163
/*
5164
5164
* If we've decided to do remote sampling, calculate the sampling rate. We
5165
5165
* need to get the number of tuples from the remote server, but skip that
5166
5166
* network round-trip if not needed.
5167
5167
*/
5168
5168
if (method != ANALYZE_SAMPLE_OFF )
5169
5169
{
5170
- reltuples = postgresCountTuplesForForeignTable (relation );
5170
+ bool can_tablesample ;
5171
+
5172
+ reltuples = postgresGetAnalyzeInfoForForeignTable (relation ,
5173
+ & can_tablesample );
5174
+
5175
+ /*
5176
+ * Make sure we're not choosing TABLESAMPLE when the remote relation does
5177
+ * not support that. But only do this for "auto" - if the user explicitly
5178
+ * requested BERNOULLI/SYSTEM, it's better to fail.
5179
+ */
5180
+ if (!can_tablesample && (method == ANALYZE_SAMPLE_AUTO ))
5181
+ method = ANALYZE_SAMPLE_RANDOM ;
5171
5182
5172
5183
/*
5173
5184
* Remote's reltuples could be 0 or -1 if the table has never been
@@ -5212,6 +5223,19 @@ postgresAcquireSampleRowsFunc(Relation relation, int elevel,
5212
5223
}
5213
5224
}
5214
5225
5226
+ /*
5227
+ * For "auto" method, pick the one we believe is best. For servers with
5228
+ * TABLESAMPLE support we pick BERNOULLI, for old servers we fall-back to
5229
+ * random() to at least reduce network transfer.
5230
+ */
5231
+ if (method == ANALYZE_SAMPLE_AUTO )
5232
+ {
5233
+ if (server_version_num < 95000 )
5234
+ method = ANALYZE_SAMPLE_RANDOM ;
5235
+ else
5236
+ method = ANALYZE_SAMPLE_BERNOULLI ;
5237
+ }
5238
+
5215
5239
/*
5216
5240
* Construct cursor that retrieves whole rows from remote.
5217
5241
*/
0 commit comments