88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.152 2010/02/26 02:00:37 momjian Exp $
11+ * $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.153 2010/08/01 22:38:11 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -92,7 +92,8 @@ static void compute_index_stats(Relation onerel, double totalrows,
9292AnlIndexData * indexdata ,int nindexes ,
9393HeapTuple * rows ,int numrows ,
9494MemoryContext col_context );
95- static VacAttrStats * examine_attribute (Relation onerel ,int attnum );
95+ static VacAttrStats * examine_attribute (Relation onerel ,int attnum ,
96+ Node * index_expr );
9697static int acquire_sample_rows (Relation onerel ,HeapTuple * rows ,
9798int targrows ,double * totalrows ,double * totaldeadrows );
9899static double random_fract (void );
@@ -339,7 +340,7 @@ do_analyze_rel(Relation onerel, VacuumStmt *vacstmt,
339340(errcode (ERRCODE_UNDEFINED_COLUMN ),
340341errmsg ("column \"%s\" of relation \"%s\" does not exist" ,
341342col ,RelationGetRelationName (onerel ))));
342- vacattrstats [tcnt ]= examine_attribute (onerel ,i );
343+ vacattrstats [tcnt ]= examine_attribute (onerel ,i , NULL );
343344if (vacattrstats [tcnt ]!= NULL )
344345tcnt ++ ;
345346}
@@ -353,7 +354,7 @@ do_analyze_rel(Relation onerel, VacuumStmt *vacstmt,
353354tcnt = 0 ;
354355for (i = 1 ;i <=attr_cnt ;i ++ )
355356{
356- vacattrstats [tcnt ]= examine_attribute (onerel ,i );
357+ vacattrstats [tcnt ]= examine_attribute (onerel ,i , NULL );
357358if (vacattrstats [tcnt ]!= NULL )
358359tcnt ++ ;
359360}
@@ -407,21 +408,8 @@ do_analyze_rel(Relation onerel, VacuumStmt *vacstmt,
407408elog (ERROR ,"too few entries in indexprs list" );
408409indexkey = (Node * )lfirst (indexpr_item );
409410indexpr_item = lnext (indexpr_item );
410-
411- /*
412- * Can't analyze if the opclass uses a storage type
413- * different from the expression result type. We'd get
414- * confused because the type shown in pg_attribute for
415- * the index column doesn't match what we are getting
416- * from the expression. Perhaps this can be fixed
417- * someday, but for now, punt.
418- */
419- if (exprType (indexkey )!=
420- Irel [ind ]-> rd_att -> attrs [i ]-> atttypid )
421- continue ;
422-
423411thisdata -> vacattrstats [tcnt ]=
424- examine_attribute (Irel [ind ],i + 1 );
412+ examine_attribute (Irel [ind ],i + 1 , indexkey );
425413if (thisdata -> vacattrstats [tcnt ]!= NULL )
426414{
427415tcnt ++ ;
@@ -802,9 +790,12 @@ compute_index_stats(Relation onerel, double totalrows,
802790 *
803791 * Determine whether the column is analyzable; if so, create and initialize
804792 * a VacAttrStats struct for it. If not, return NULL.
793+ *
794+ * If index_expr isn't NULL, then we're trying to analyze an expression index,
795+ * and index_expr is the expression tree representing the column's data.
805796 */
806797static VacAttrStats *
807- examine_attribute (Relation onerel ,int attnum )
798+ examine_attribute (Relation onerel ,int attnum , Node * index_expr )
808799{
809800Form_pg_attribute attr = onerel -> rd_att -> attrs [attnum - 1 ];
810801HeapTuple typtuple ;
@@ -827,9 +818,30 @@ examine_attribute(Relation onerel, int attnum)
827818stats = (VacAttrStats * )palloc0 (sizeof (VacAttrStats ));
828819stats -> attr = (Form_pg_attribute )palloc (ATTRIBUTE_FIXED_PART_SIZE );
829820memcpy (stats -> attr ,attr ,ATTRIBUTE_FIXED_PART_SIZE );
830- typtuple = SearchSysCache1 (TYPEOID ,ObjectIdGetDatum (attr -> atttypid ));
821+
822+ /*
823+ * When analyzing an expression index, believe the expression tree's type
824+ * not the column datatype --- the latter might be the opckeytype storage
825+ * type of the opclass, which is not interesting for our purposes. (Note:
826+ * if we did anything with non-expression index columns, we'd need to
827+ * figure out where to get the correct type info from, but for now that's
828+ * not a problem.) It's not clear whether anyone will care about the
829+ * typmod, but we store that too just in case.
830+ */
831+ if (index_expr )
832+ {
833+ stats -> attrtypid = exprType (index_expr );
834+ stats -> attrtypmod = exprTypmod (index_expr );
835+ }
836+ else
837+ {
838+ stats -> attrtypid = attr -> atttypid ;
839+ stats -> attrtypmod = attr -> atttypmod ;
840+ }
841+
842+ typtuple = SearchSysCache1 (TYPEOID ,ObjectIdGetDatum (stats -> attrtypid ));
831843if (!HeapTupleIsValid (typtuple ))
832- elog (ERROR ,"cache lookup failed for type %u" ,attr -> atttypid );
844+ elog (ERROR ,"cache lookup failed for type %u" ,stats -> attrtypid );
833845stats -> attrtype = (Form_pg_type )palloc (sizeof (FormData_pg_type ));
834846memcpy (stats -> attrtype ,GETSTRUCT (typtuple ),sizeof (FormData_pg_type ));
835847ReleaseSysCache (typtuple );
@@ -838,12 +850,12 @@ examine_attribute(Relation onerel, int attnum)
838850
839851/*
840852 * The fields describing the stats->stavalues[n] element types default to
841- * the type of thefield being analyzed, but the type-specific typanalyze
853+ * the type of thedata being analyzed, but the type-specific typanalyze
842854 * function can change them if it wants to store something else.
843855 */
844856for (i = 0 ;i < STATISTIC_NUM_SLOTS ;i ++ )
845857{
846- stats -> statypid [i ]= stats -> attr -> atttypid ;
858+ stats -> statypid [i ]= stats -> attrtypid ;
847859stats -> statyplen [i ]= stats -> attrtype -> typlen ;
848860stats -> statypbyval [i ]= stats -> attrtype -> typbyval ;
849861stats -> statypalign [i ]= stats -> attrtype -> typalign ;
@@ -1780,7 +1792,7 @@ std_typanalyze(VacAttrStats *stats)
17801792attr -> attstattarget = default_statistics_target ;
17811793
17821794/* Look for default "<" and "=" operators for column's type */
1783- get_sort_group_operators (attr -> atttypid ,
1795+ get_sort_group_operators (stats -> attrtypid ,
17841796 false, false, false,
17851797& ltopr ,& eqopr ,NULL );
17861798
@@ -1860,10 +1872,10 @@ compute_minimal_stats(VacAttrStatsP stats,
18601872int nonnull_cnt = 0 ;
18611873int toowide_cnt = 0 ;
18621874double total_width = 0 ;
1863- bool is_varlena = (!stats -> attr -> attbyval &&
1864- stats -> attr -> attlen == -1 );
1865- bool is_varwidth = (!stats -> attr -> attbyval &&
1866- stats -> attr -> attlen < 0 );
1875+ bool is_varlena = (!stats -> attrtype -> typbyval &&
1876+ stats -> attrtype -> typlen == -1 );
1877+ bool is_varwidth = (!stats -> attrtype -> typbyval &&
1878+ stats -> attrtype -> typlen < 0 );
18671879FmgrInfo f_cmpeq ;
18681880typedef struct
18691881{
@@ -2126,8 +2138,8 @@ compute_minimal_stats(VacAttrStatsP stats,
21262138for (i = 0 ;i < num_mcv ;i ++ )
21272139{
21282140mcv_values [i ]= datumCopy (track [i ].value ,
2129- stats -> attr -> attbyval ,
2130- stats -> attr -> attlen );
2141+ stats -> attrtype -> typbyval ,
2142+ stats -> attrtype -> typlen );
21312143mcv_freqs [i ]= (double )track [i ].count / (double )samplerows ;
21322144}
21332145MemoryContextSwitchTo (old_context );
@@ -2184,10 +2196,10 @@ compute_scalar_stats(VacAttrStatsP stats,
21842196int nonnull_cnt = 0 ;
21852197int toowide_cnt = 0 ;
21862198double total_width = 0 ;
2187- bool is_varlena = (!stats -> attr -> attbyval &&
2188- stats -> attr -> attlen == -1 );
2189- bool is_varwidth = (!stats -> attr -> attbyval &&
2190- stats -> attr -> attlen < 0 );
2199+ bool is_varlena = (!stats -> attrtype -> typbyval &&
2200+ stats -> attrtype -> typlen == -1 );
2201+ bool is_varwidth = (!stats -> attrtype -> typbyval &&
2202+ stats -> attrtype -> typlen < 0 );
21912203double corr_xysum ;
21922204Oid cmpFn ;
21932205int cmpFlags ;
@@ -2476,8 +2488,8 @@ compute_scalar_stats(VacAttrStatsP stats,
24762488for (i = 0 ;i < num_mcv ;i ++ )
24772489{
24782490mcv_values [i ]= datumCopy (values [track [i ].first ].value ,
2479- stats -> attr -> attbyval ,
2480- stats -> attr -> attlen );
2491+ stats -> attrtype -> typbyval ,
2492+ stats -> attrtype -> typlen );
24812493mcv_freqs [i ]= (double )track [i ].count / (double )samplerows ;
24822494}
24832495MemoryContextSwitchTo (old_context );
@@ -2583,8 +2595,8 @@ compute_scalar_stats(VacAttrStatsP stats,
25832595for (i = 0 ;i < num_hist ;i ++ )
25842596{
25852597hist_values [i ]= datumCopy (values [pos ].value ,
2586- stats -> attr -> attbyval ,
2587- stats -> attr -> attlen );
2598+ stats -> attrtype -> typbyval ,
2599+ stats -> attrtype -> typlen );
25882600pos += delta ;
25892601posfrac += deltafrac ;
25902602if (posfrac >= (num_hist - 1 ))