88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.68 2004/02/12 23:41:02 tgl Exp $
11+ * $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.69 2004/02/13 06:39:49 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -52,6 +52,7 @@ static double init_selection_state(int n);
5252static double select_next_random_record (double t ,int n ,double * stateptr );
5353static int compare_rows (const void * a ,const void * b );
5454static void update_attstats (Oid relid ,int natts ,VacAttrStats * * vacattrstats );
55+ static Datum std_fetch_func (VacAttrStatsP stats ,int rownum ,bool * isNull );
5556
5657static bool std_typanalyze (VacAttrStats * stats );
5758
@@ -259,12 +260,14 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
259260old_context = MemoryContextSwitchTo (col_context );
260261for (i = 0 ;i < attr_cnt ;i ++ )
261262{
262- (* vacattrstats [i ]-> compute_stats ) (vacattrstats [i ],
263- vacattrstats [i ]-> tupattnum ,
264- onerel -> rd_att ,
265- totalrows ,
266- rows ,
267- numrows );
263+ VacAttrStats * stats = vacattrstats [i ];
264+
265+ stats -> rows = rows ;
266+ stats -> tupDesc = onerel -> rd_att ;
267+ (* stats -> compute_stats ) (stats ,
268+ std_fetch_func ,
269+ numrows ,
270+ totalrows );
268271MemoryContextResetAndDeleteChildren (col_context );
269272}
270273MemoryContextSwitchTo (old_context );
@@ -861,6 +864,22 @@ update_attstats(Oid relid, int natts, VacAttrStats **vacattrstats)
861864heap_close (sd ,RowExclusiveLock );
862865}
863866
867+ /*
868+ * Standard fetch function for use by compute_stats subroutines.
869+ *
870+ * This exists to provide some insulation between compute_stats routines
871+ * and the actual storage of the sample data.
872+ */
873+ static Datum
874+ std_fetch_func (VacAttrStatsP stats ,int rownum ,bool * isNull )
875+ {
876+ int attnum = stats -> tupattnum ;
877+ HeapTuple tuple = stats -> rows [rownum ];
878+ TupleDesc tupDesc = stats -> tupDesc ;
879+
880+ return heap_getattr (tuple ,attnum ,tupDesc ,isNull );
881+ }
882+
864883
865884/*==========================================================================
866885 *
@@ -915,12 +934,14 @@ static SortFunctionKind datumCmpFnKind;
915934static int * datumCmpTupnoLink ;
916935
917936
918- static void compute_minimal_stats (VacAttrStats * stats ,int attnum ,
919- TupleDesc tupDesc ,double totalrows ,
920- HeapTuple * rows ,int numrows );
921- static void compute_scalar_stats (VacAttrStats * stats ,int attnum ,
922- TupleDesc tupDesc ,double totalrows ,
923- HeapTuple * rows ,int numrows );
937+ static void compute_minimal_stats (VacAttrStatsP stats ,
938+ AnalyzeAttrFetchFunc fetchfunc ,
939+ int samplerows ,
940+ double totalrows );
941+ static void compute_scalar_stats (VacAttrStatsP stats ,
942+ AnalyzeAttrFetchFunc fetchfunc ,
943+ int samplerows ,
944+ double totalrows );
924945static int compare_scalars (const void * a ,const void * b );
925946static int compare_mcvs (const void * a ,const void * b );
926947
@@ -1024,9 +1045,10 @@ std_typanalyze(VacAttrStats *stats)
10241045 *depend mainly on the length of the list we are willing to keep.
10251046 */
10261047static void
1027- compute_minimal_stats (VacAttrStats * stats ,int attnum ,
1028- TupleDesc tupDesc ,double totalrows ,
1029- HeapTuple * rows ,int numrows )
1048+ compute_minimal_stats (VacAttrStatsP stats ,
1049+ AnalyzeAttrFetchFunc fetchfunc ,
1050+ int samplerows ,
1051+ double totalrows )
10301052{
10311053int i ;
10321054int null_cnt = 0 ;
@@ -1061,9 +1083,8 @@ compute_minimal_stats(VacAttrStats *stats, int attnum,
10611083
10621084fmgr_info (mystats -> eqfunc ,& f_cmpeq );
10631085
1064- for (i = 0 ;i < numrows ;i ++ )
1086+ for (i = 0 ;i < samplerows ;i ++ )
10651087{
1066- HeapTuple tuple = rows [i ];
10671088Datum value ;
10681089bool isnull ;
10691090bool match ;
@@ -1072,7 +1093,7 @@ compute_minimal_stats(VacAttrStats *stats, int attnum,
10721093
10731094vacuum_delay_point ();
10741095
1075- value = heap_getattr ( tuple , attnum , tupDesc ,& isnull );
1096+ value = fetchfunc ( stats , i ,& isnull );
10761097
10771098/* Check for null/nonnull */
10781099if (isnull )
@@ -1166,7 +1187,7 @@ compute_minimal_stats(VacAttrStats *stats, int attnum,
11661187
11671188stats -> stats_valid = true;
11681189/* Do the simple null-frac and width stats */
1169- stats -> stanullfrac = (double )null_cnt / (double )numrows ;
1190+ stats -> stanullfrac = (double )null_cnt / (double )samplerows ;
11701191if (is_varwidth )
11711192stats -> stawidth = total_width / (double )nonnull_cnt ;
11721193else
@@ -1222,10 +1243,10 @@ compute_minimal_stats(VacAttrStats *stats, int attnum,
12221243denom ,
12231244stadistinct ;
12241245
1225- numer = (double )numrows * (double )d ;
1246+ numer = (double )samplerows * (double )d ;
12261247
1227- denom = (double ) (numrows - f1 )+
1228- (double )f1 * (double )numrows /totalrows ;
1248+ denom = (double ) (samplerows - f1 )+
1249+ (double )f1 * (double )samplerows /totalrows ;
12291250
12301251stadistinct = numer /denom ;
12311252/* Clamp to sane range in case of roundoff error */
@@ -1270,7 +1291,7 @@ compute_minimal_stats(VacAttrStats *stats, int attnum,
12701291if (ndistinct < 0 )
12711292ndistinct = - ndistinct * totalrows ;
12721293/* estimate # of occurrences in sample of a typical value */
1273- avgcount = (double )numrows /ndistinct ;
1294+ avgcount = (double )samplerows /ndistinct ;
12741295/* set minimum threshold count to store a value */
12751296mincount = avgcount * 1.25 ;
12761297if (mincount < 2 )
@@ -1303,7 +1324,7 @@ compute_minimal_stats(VacAttrStats *stats, int attnum,
13031324mcv_values [i ]= datumCopy (track [i ].value ,
13041325stats -> attr -> attbyval ,
13051326stats -> attr -> attlen );
1306- mcv_freqs [i ]= (double )track [i ].count / (double )numrows ;
1327+ mcv_freqs [i ]= (double )track [i ].count / (double )samplerows ;
13071328}
13081329MemoryContextSwitchTo (old_context );
13091330
@@ -1333,9 +1354,10 @@ compute_minimal_stats(VacAttrStats *stats, int attnum,
13331354 *data values into order.
13341355 */
13351356static void
1336- compute_scalar_stats (VacAttrStats * stats ,int attnum ,
1337- TupleDesc tupDesc ,double totalrows ,
1338- HeapTuple * rows ,int numrows )
1357+ compute_scalar_stats (VacAttrStatsP stats ,
1358+ AnalyzeAttrFetchFunc fetchfunc ,
1359+ int samplerows ,
1360+ double totalrows )
13391361{
13401362int i ;
13411363int null_cnt = 0 ;
@@ -1359,23 +1381,22 @@ compute_scalar_stats(VacAttrStats *stats, int attnum,
13591381int num_bins = stats -> attr -> attstattarget ;
13601382StdAnalyzeData * mystats = (StdAnalyzeData * )stats -> extra_data ;
13611383
1362- values = (ScalarItem * )palloc (numrows * sizeof (ScalarItem ));
1363- tupnoLink = (int * )palloc (numrows * sizeof (int ));
1384+ values = (ScalarItem * )palloc (samplerows * sizeof (ScalarItem ));
1385+ tupnoLink = (int * )palloc (samplerows * sizeof (int ));
13641386track = (ScalarMCVItem * )palloc (num_mcv * sizeof (ScalarMCVItem ));
13651387
13661388SelectSortFunction (mystats -> ltopr ,& cmpFn ,& cmpFnKind );
13671389fmgr_info (cmpFn ,& f_cmpfn );
13681390
13691391/* Initial scan to find sortable values */
1370- for (i = 0 ;i < numrows ;i ++ )
1392+ for (i = 0 ;i < samplerows ;i ++ )
13711393{
1372- HeapTuple tuple = rows [i ];
13731394Datum value ;
13741395bool isnull ;
13751396
13761397vacuum_delay_point ();
13771398
1378- value = heap_getattr ( tuple , attnum , tupDesc ,& isnull );
1399+ value = fetchfunc ( stats , i ,& isnull );
13791400
13801401/* Check for null/nonnull */
13811402if (isnull )
@@ -1505,7 +1526,7 @@ compute_scalar_stats(VacAttrStats *stats, int attnum,
15051526
15061527stats -> stats_valid = true;
15071528/* Do the simple null-frac and width stats */
1508- stats -> stanullfrac = (double )null_cnt / (double )numrows ;
1529+ stats -> stanullfrac = (double )null_cnt / (double )samplerows ;
15091530if (is_varwidth )
15101531stats -> stawidth = total_width / (double )nonnull_cnt ;
15111532else
@@ -1546,10 +1567,10 @@ compute_scalar_stats(VacAttrStats *stats, int attnum,
15461567denom ,
15471568stadistinct ;
15481569
1549- numer = (double )numrows * (double )d ;
1570+ numer = (double )samplerows * (double )d ;
15501571
1551- denom = (double ) (numrows - f1 )+
1552- (double )f1 * (double )numrows /totalrows ;
1572+ denom = (double ) (samplerows - f1 )+
1573+ (double )f1 * (double )samplerows /totalrows ;
15531574
15541575stadistinct = numer /denom ;
15551576/* Clamp to sane range in case of roundoff error */
@@ -1599,13 +1620,13 @@ compute_scalar_stats(VacAttrStats *stats, int attnum,
15991620if (ndistinct < 0 )
16001621ndistinct = - ndistinct * totalrows ;
16011622/* estimate # of occurrences in sample of a typical value */
1602- avgcount = (double )numrows /ndistinct ;
1623+ avgcount = (double )samplerows /ndistinct ;
16031624/* set minimum threshold count to store a value */
16041625mincount = avgcount * 1.25 ;
16051626if (mincount < 2 )
16061627mincount = 2 ;
16071628/* don't let threshold exceed 1/K, however */
1608- maxmincount = (double )numrows / (double )num_bins ;
1629+ maxmincount = (double )samplerows / (double )num_bins ;
16091630if (mincount > maxmincount )
16101631mincount = maxmincount ;
16111632if (num_mcv > track_cnt )
@@ -1636,7 +1657,7 @@ compute_scalar_stats(VacAttrStats *stats, int attnum,
16361657mcv_values [i ]= datumCopy (values [track [i ].first ].value ,
16371658stats -> attr -> attbyval ,
16381659stats -> attr -> attlen );
1639- mcv_freqs [i ]= (double )track [i ].count / (double )numrows ;
1660+ mcv_freqs [i ]= (double )track [i ].count / (double )samplerows ;
16401661}
16411662MemoryContextSwitchTo (old_context );
16421663