@@ -259,6 +259,9 @@ postgresGetForeignRelSize(PlannerInfo *root,
259259 int width ;
260260 Cost startup_cost ;
261261 Cost total_cost ;
262+ Cost run_cost ;
263+ QualCost qpqual_cost ;
264+ Cost cpu_per_tuple ;
262265 List * remote_conds ;
263266 List * param_conds ;
264267 List * local_conds ;
@@ -349,6 +352,16 @@ postgresGetForeignRelSize(PlannerInfo *root,
349352 sel *= clauselist_selectivity (root , local_conds ,
350353 baserel -> relid , JOIN_INNER , NULL );
351354
355+ /*
356+ * Add in the eval cost of those conditions, too.
357+ */
358+ cost_qual_eval (& qpqual_cost , param_conds , root );
359+ startup_cost += qpqual_cost .startup ;
360+ total_cost += qpqual_cost .per_tuple * rows ;
361+ cost_qual_eval (& qpqual_cost , local_conds , root );
362+ startup_cost += qpqual_cost .startup ;
363+ total_cost += qpqual_cost .per_tuple * rows ;
364+
352365 /* Report estimated numbers to planner. */
353366 baserel -> rows = clamp_row_est (rows * sel );
354367 baserel -> width = width ;
@@ -367,18 +380,25 @@ postgresGetForeignRelSize(PlannerInfo *root,
367380 * estimate of 10 pages, and divide by the column-datatype-based width
368381 * estimate to get the corresponding number of tuples.
369382 */
370- if (baserel -> tuples <= 0 )
383+ if (baserel -> pages == 0 && baserel -> tuples == 0 )
384+ {
385+ baserel -> pages = 10 ;
371386 baserel -> tuples =
372387 (10 * BLCKSZ ) / (baserel -> width + sizeof (HeapTupleHeaderData ));
388+ }
373389
374390 set_baserel_size_estimates (root , baserel );
375391
376- /*
377- * XXX need to do something here to calculate sane startup and total
378- * cost estimates ... for the moment, we do this:
379- */
392+ /* Cost as though this were a seqscan, which is pessimistic. */
380393 startup_cost = 0 ;
381- total_cost = baserel -> rows * cpu_tuple_cost ;
394+ run_cost = 0 ;
395+ run_cost += seq_page_cost * baserel -> pages ;
396+
397+ startup_cost += baserel -> baserestrictcost .startup ;
398+ cpu_per_tuple = cpu_tuple_cost + baserel -> baserestrictcost .per_tuple ;
399+ run_cost += cpu_per_tuple * baserel -> tuples ;
400+
401+ total_cost = startup_cost + run_cost ;
382402 }
383403
384404 /*
@@ -1068,9 +1088,62 @@ postgresAnalyzeForeignTable(Relation relation,
10681088 AcquireSampleRowsFunc * func ,
10691089 BlockNumber * totalpages )
10701090{
1071- * totalpages = 0 ; /* XXX this is probably a bad idea */
1091+ ForeignTable * table ;
1092+ ForeignServer * server ;
1093+ UserMapping * user ;
1094+ PGconn * conn ;
1095+ StringInfoData sql ;
1096+ PGresult * volatile res = NULL ;
1097+
1098+ /* Return the row-analysis function pointer */
10721099 * func = postgresAcquireSampleRowsFunc ;
10731100
1101+ /*
1102+ * Now we have to get the number of pages. It's annoying that the ANALYZE
1103+ * API requires us to return that now, because it forces some duplication
1104+ * of effort between this routine and postgresAcquireSampleRowsFunc. But
1105+ * it's probably not worth redefining that API at this point.
1106+ */
1107+
1108+ /*
1109+ * Get the connection to use. We do the remote access as the table's
1110+ * owner, even if the ANALYZE was started by some other user.
1111+ */
1112+ table = GetForeignTable (RelationGetRelid (relation ));
1113+ server = GetForeignServer (table -> serverid );
1114+ user = GetUserMapping (relation -> rd_rel -> relowner , server -> serverid );
1115+ conn = GetConnection (server , user );
1116+
1117+ /*
1118+ * Construct command to get page count for relation.
1119+ */
1120+ initStringInfo (& sql );
1121+ deparseAnalyzeSizeSql (& sql , relation );
1122+
1123+ /* In what follows, do not risk leaking any PGresults. */
1124+ PG_TRY ();
1125+ {
1126+ res = PQexec (conn , sql .data );
1127+ if (PQresultStatus (res ) != PGRES_TUPLES_OK )
1128+ pgfdw_report_error (ERROR , res , false, sql .data );
1129+
1130+ if (PQntuples (res ) != 1 || PQnfields (res ) != 1 )
1131+ elog (ERROR , "unexpected result from deparseAnalyzeSizeSql query" );
1132+ * totalpages = strtoul (PQgetvalue (res , 0 , 0 ), NULL , 10 );
1133+
1134+ PQclear (res );
1135+ res = NULL ;
1136+ }
1137+ PG_CATCH ();
1138+ {
1139+ if (res )
1140+ PQclear (res );
1141+ PG_RE_THROW ();
1142+ }
1143+ PG_END_TRY ();
1144+
1145+ ReleaseConnection (conn );
1146+
10741147 return true;
10751148}
10761149
0 commit comments