Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit cea49fe

Browse files
committed
Dept of second thoughts: improve the API for AnalyzeForeignTable.
If we make the initially-called function return the table physical-size estimate, acquire_inherited_sample_rows will be able to use that to allocate numbers of samples among child tables, when the day comes that we want to support foreign tables in inheritance trees.
1 parent 263d9de commit cea49fe

File tree

4 files changed

+101
-98
lines changed

4 files changed

+101
-98
lines changed

contrib/file_fdw/file_fdw.c

Lines changed: 40 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,9 @@ static void fileBeginForeignScan(ForeignScanState *node, int eflags);
125125
static TupleTableSlot *fileIterateForeignScan(ForeignScanState *node);
126126
static void fileReScanForeignScan(ForeignScanState *node);
127127
static void fileEndForeignScan(ForeignScanState *node);
128-
static AcquireSampleRowsFunc fileAnalyzeForeignTable(Relation relation);
128+
static bool fileAnalyzeForeignTable(Relation relation,
129+
AcquireSampleRowsFunc *func,
130+
BlockNumber *totalpages);
129131

130132
/*
131133
* Helper functions
@@ -141,8 +143,7 @@ static void estimate_costs(PlannerInfo *root, RelOptInfo *baserel,
141143
Cost *startup_cost, Cost *total_cost);
142144
static int file_acquire_sample_rows(Relation onerel, int elevel,
143145
HeapTuple *rows, int targrows,
144-
double *totalrows, double *totaldeadrows,
145-
BlockNumber *totalpages);
146+
double *totalrows, double *totaldeadrows);
146147

147148

148149
/*
@@ -656,10 +657,39 @@ fileEndForeignScan(ForeignScanState *node)
656657
* fileAnalyzeForeignTable
657658
* Test whether analyzing this foreign table is supported
658659
*/
659-
static AcquireSampleRowsFunc
660-
fileAnalyzeForeignTable(Relation relation)
660+
static bool
661+
fileAnalyzeForeignTable(Relation relation,
662+
AcquireSampleRowsFunc *func,
663+
BlockNumber *totalpages)
661664
{
662-
return file_acquire_sample_rows;
665+
char *filename;
666+
List *options;
667+
struct stat stat_buf;
668+
669+
/* Fetch options of foreign table */
670+
fileGetOptions(RelationGetRelid(relation), &filename, &options);
671+
672+
/*
673+
* Get size of the file. (XXX if we fail here, would it be better to
674+
* just return false to skip analyzing the table?)
675+
*/
676+
if (stat(filename, &stat_buf) < 0)
677+
ereport(ERROR,
678+
(errcode_for_file_access(),
679+
errmsg("could not stat file \"%s\": %m",
680+
filename)));
681+
682+
/*
683+
* Convert size to pages. Must return at least 1 so that we can tell
684+
* later on that pg_class.relpages is not default.
685+
*/
686+
*totalpages = (stat_buf.st_size + (BLCKSZ - 1)) / BLCKSZ;
687+
if (*totalpages < 1)
688+
*totalpages = 1;
689+
690+
*func = file_acquire_sample_rows;
691+
692+
return true;
663693
}
664694

665695
/*
@@ -780,8 +810,7 @@ estimate_costs(PlannerInfo *root, RelOptInfo *baserel,
780810
* which must have at least targrows entries.
781811
* The actual number of rows selected is returned as the function result.
782812
* We also count the total number of rows in the file and return it into
783-
* *totalrows, and return the file's physical size in *totalpages.
784-
* Note that *totaldeadrows is always set to 0.
813+
* *totalrows. Note that *totaldeadrows is always set to 0.
785814
*
786815
* Note that the returned list of rows is not always in order by physical
787816
* position in the file. Therefore, correlation estimates derived later
@@ -791,8 +820,7 @@ estimate_costs(PlannerInfo *root, RelOptInfo *baserel,
791820
static int
792821
file_acquire_sample_rows(Relation onerel, int elevel,
793822
HeapTuple *rows, int targrows,
794-
double *totalrows, double *totaldeadrows,
795-
BlockNumber *totalpages)
823+
double *totalrows, double *totaldeadrows)
796824
{
797825
int numrows = 0;
798826
double rowstoskip = -1; /* -1 means not set yet */
@@ -802,7 +830,6 @@ file_acquire_sample_rows(Relation onerel, int elevel,
802830
bool *nulls;
803831
bool found;
804832
char *filename;
805-
struct stat stat_buf;
806833
List *options;
807834
CopyState cstate;
808835
ErrorContextCallback errcontext;
@@ -819,22 +846,6 @@ file_acquire_sample_rows(Relation onerel, int elevel,
819846
/* Fetch options of foreign table */
820847
fileGetOptions(RelationGetRelid(onerel), &filename, &options);
821848

822-
/*
823-
* Get size of the file.
824-
*/
825-
if (stat(filename, &stat_buf) < 0)
826-
ereport(ERROR,
827-
(errcode_for_file_access(),
828-
errmsg("could not stat file \"%s\": %m",
829-
filename)));
830-
831-
/*
832-
* Convert size to pages for use in I/O cost estimate.
833-
*/
834-
*totalpages = (stat_buf.st_size + (BLCKSZ - 1)) / BLCKSZ;
835-
if (*totalpages < 1)
836-
*totalpages = 1;
837-
838849
/*
839850
* Create CopyState from FDW options.
840851
*/
@@ -931,10 +942,10 @@ file_acquire_sample_rows(Relation onerel, int elevel,
931942
* Emit some interesting relation info
932943
*/
933944
ereport(elevel,
934-
(errmsg("\"%s\": scanned %u pages containing %.0f rows; "
945+
(errmsg("\"%s\": file contains %.0f rows; "
935946
"%d rows in sample",
936947
RelationGetRelationName(onerel),
937-
*totalpages, *totalrows, numrows)));
948+
*totalrows, numrows)));
938949

939950
return numrows;
940951
}

doc/src/sgml/fdwhandler.sgml

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -279,15 +279,19 @@ EndForeignScan (ForeignScanState *node);
279279

280280
<para>
281281
<programlisting>
282-
AcquireSampleRowsFunc
283-
AnalyzeForeignTable (Relation relation);
282+
bool
283+
AnalyzeForeignTable (Relation relation,
284+
AcquireSampleRowsFunc *func,
285+
BlockNumber *totalpages);
284286
</programlisting>
285287

286288
This function is called when <xref linkend="sql-analyze"> is executed on
287-
a foreign table. If the FDW supports collecting statistics for this
288-
foreign table, it should return a pointer to a function that will collect
289-
sample rows from the table. Otherwise, return <literal>NULL</>. If the
290-
FDW does not support collecting statistics for any tables, the
289+
a foreign table. If the FDW can collect statistics for this
290+
foreign table, it should return <literal>true</>, and provide a pointer
291+
to a function that will collect sample rows from the table in
292+
<parameter>func</>, plus the estimated size of the table in pages in
293+
<parameter>totalpages</>. Otherwise, return <literal>false</>.
294+
If the FDW does not support collecting statistics for any tables, the
291295
<function>AnalyzeForeignTable</> pointer can be set to <literal>NULL</>.
292296
</para>
293297

@@ -298,18 +302,16 @@ int
298302
AcquireSampleRowsFunc (Relation relation, int elevel,
299303
HeapTuple *rows, int targrows,
300304
double *totalrows,
301-
double *totaldeadrows,
302-
BlockNumber *totalpages);
305+
double *totaldeadrows);
303306
</programlisting>
304307

305308
A random sample of up to <parameter>targrows</> rows should be collected
306309
from the table and stored into the caller-provided <parameter>rows</>
307310
array. The actual number of rows collected must be returned. In
308-
addition, store estimates of the total numbers of live rows, dead rows,
309-
and pages in the table into the output parameters
310-
<parameter>totalrows</>, <parameter>totaldeadrows</>, and
311-
<parameter>totalpages</>. These numbers will be recorded in the table's
312-
<structname>pg_class</> entry for future use.
311+
addition, store estimates of the total numbers of live and dead rows in
312+
the table into the output parameters <parameter>totalrows</> and
313+
<parameter>totaldeadrows</>. (Set <parameter>totaldeadrows</> to zero
314+
if the FDW does not have any concept of dead rows.)
313315
</para>
314316

315317
<para>

0 commit comments

Comments
 (0)