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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy