@ -4974,11 +4974,14 @@ postgresAnalyzeForeignTable(Relation relation,
}
}
/*
/*
* postgresCountTuples ForForeignTable
* postgresGetAnalyzeInfo ForForeignTable
* Count tuples in foreign table ( just get pg_class . reltuples ) .
* Count tuples in foreign table ( just get pg_class . reltuples ) .
*
* can_tablesample determines if the remote relation supports acquiring the
* sample using TABLESAMPLE .
*/
*/
static double
static double
postgresCountTuplesForForeignTable ( Relation relation )
postgresGetAnalyzeInfo ForForeignTable ( Relation relation , bool * can_tablesample )
{
{
ForeignTable * table ;
ForeignTable * table ;
UserMapping * user ;
UserMapping * user ;
@ -4986,6 +4989,10 @@ postgresCountTuplesForForeignTable(Relation relation)
StringInfoData sql ;
StringInfoData sql ;
PGresult * volatile res = NULL ;
PGresult * volatile res = NULL ;
volatile double reltuples = - 1 ;
volatile double reltuples = - 1 ;
volatile char relkind = 0 ;
/* assume the remote relation does not support TABLESAMPLE */
* can_tablesample = false ;
/*
/*
* Get the connection to use . We do the remote access as the table ' s
* Get the connection to use . We do the remote access as the table ' s
@ -4999,7 +5006,7 @@ postgresCountTuplesForForeignTable(Relation relation)
* Construct command to get page count for relation .
* Construct command to get page count for relation .
*/
*/
initStringInfo ( & sql ) ;
initStringInfo ( & sql ) ;
deparseAnalyzeTuples Sql ( & sql , relation ) ;
deparseAnalyzeInfo Sql ( & sql , relation ) ;
/* In what follows, do not risk leaking any PGresults. */
/* In what follows, do not risk leaking any PGresults. */
PG_TRY ( ) ;
PG_TRY ( ) ;
@ -5008,9 +5015,10 @@ postgresCountTuplesForForeignTable(Relation relation)
if ( PQresultStatus ( res ) ! = PGRES_TUPLES_OK )
if ( PQresultStatus ( res ) ! = PGRES_TUPLES_OK )
pgfdw_report_error ( ERROR , res , conn , false , sql . data ) ;
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 " ) ;
elog ( ERROR , " unexpected result from deparseAnalyzeTuplesSql query " ) ;
reltuples = strtod ( PQgetvalue ( res , 0 , 0 ) , NULL ) ;
reltuples = strtod ( PQgetvalue ( res , 0 , 0 ) , NULL ) ;
relkind = * ( PQgetvalue ( res , 0 , 1 ) ) ;
}
}
PG_FINALLY ( ) ;
PG_FINALLY ( ) ;
{
{
@ -5021,6 +5029,11 @@ postgresCountTuplesForForeignTable(Relation relation)
ReleaseConnection ( conn ) ;
ReleaseConnection ( conn ) ;
/* TABLESAMPLE is supported only for regular tables and matviews */
* can_tablesample = ( relkind = = RELKIND_RELATION | |
relkind = = RELKIND_MATVIEW | |
relkind = = RELKIND_PARTITIONED_TABLE ) ;
return reltuples ;
return reltuples ;
}
}
@ -5147,19 +5160,6 @@ postgresAcquireSampleRowsFunc(Relation relation, int elevel,
( errcode ( ERRCODE_FEATURE_NOT_SUPPORTED ) ,
( errcode ( ERRCODE_FEATURE_NOT_SUPPORTED ) ,
errmsg ( " remote server does not support TABLESAMPLE feature " ) ) ) ;
errmsg ( " remote server does not support TABLESAMPLE feature " ) ) ) ;
/*
* For " auto " method , pick the one we believe is best . For servers with
* TABLESAMPLE support we pick BERNOULLI , for old servers we fall - back to
* random ( ) to at least reduce network transfer .
*/
if ( method = = ANALYZE_SAMPLE_AUTO )
{
if ( server_version_num < 95000 )
method = ANALYZE_SAMPLE_RANDOM ;
else
method = ANALYZE_SAMPLE_BERNOULLI ;
}
/*
/*
* If we ' ve decided to do remote sampling , calculate the sampling rate . We
* If we ' ve decided to do remote sampling , calculate the sampling rate . We
* need to get the number of tuples from the remote server , but skip that
* need to get the number of tuples from the remote server , but skip that
@ -5167,7 +5167,18 @@ postgresAcquireSampleRowsFunc(Relation relation, int elevel,
*/
*/
if ( method ! = ANALYZE_SAMPLE_OFF )
if ( method ! = ANALYZE_SAMPLE_OFF )
{
{
reltuples = postgresCountTuplesForForeignTable ( relation ) ;
bool can_tablesample ;
reltuples = postgresGetAnalyzeInfoForForeignTable ( relation ,
& can_tablesample ) ;
/*
* Make sure we ' re not choosing TABLESAMPLE when the remote relation does
* not support that . But only do this for " auto " - if the user explicitly
* requested BERNOULLI / SYSTEM , it ' s better to fail .
*/
if ( ! can_tablesample & & ( method = = ANALYZE_SAMPLE_AUTO ) )
method = ANALYZE_SAMPLE_RANDOM ;
/*
/*
* Remote ' s reltuples could be 0 or - 1 if the table has never been
* Remote ' s reltuples could be 0 or - 1 if the table has never been
@ -5212,6 +5223,19 @@ postgresAcquireSampleRowsFunc(Relation relation, int elevel,
}
}
}
}
/*
* For " auto " method , pick the one we believe is best . For servers with
* TABLESAMPLE support we pick BERNOULLI , for old servers we fall - back to
* random ( ) to at least reduce network transfer .
*/
if ( method = = ANALYZE_SAMPLE_AUTO )
{
if ( server_version_num < 95000 )
method = ANALYZE_SAMPLE_RANDOM ;
else
method = ANALYZE_SAMPLE_BERNOULLI ;
}
/*
/*
* Construct cursor that retrieves whole rows from remote .
* Construct cursor that retrieves whole rows from remote .
*/
*/