8
8
*
9
9
*
10
10
* 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 $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -92,7 +92,8 @@ static void compute_index_stats(Relation onerel, double totalrows,
92
92
AnlIndexData * indexdata , int nindexes ,
93
93
HeapTuple * rows , int numrows ,
94
94
MemoryContext col_context );
95
- static VacAttrStats * examine_attribute (Relation onerel , int attnum );
95
+ static VacAttrStats * examine_attribute (Relation onerel , int attnum ,
96
+ Node * index_expr );
96
97
static int acquire_sample_rows (Relation onerel , HeapTuple * rows ,
97
98
int targrows , double * totalrows , double * totaldeadrows );
98
99
static double random_fract (void );
@@ -339,7 +340,7 @@ do_analyze_rel(Relation onerel, VacuumStmt *vacstmt,
339
340
(errcode (ERRCODE_UNDEFINED_COLUMN ),
340
341
errmsg ("column \"%s\" of relation \"%s\" does not exist" ,
341
342
col , RelationGetRelationName (onerel ))));
342
- vacattrstats [tcnt ] = examine_attribute (onerel , i );
343
+ vacattrstats [tcnt ] = examine_attribute (onerel , i , NULL );
343
344
if (vacattrstats [tcnt ] != NULL )
344
345
tcnt ++ ;
345
346
}
@@ -353,7 +354,7 @@ do_analyze_rel(Relation onerel, VacuumStmt *vacstmt,
353
354
tcnt = 0 ;
354
355
for (i = 1 ; i <= attr_cnt ; i ++ )
355
356
{
356
- vacattrstats [tcnt ] = examine_attribute (onerel , i );
357
+ vacattrstats [tcnt ] = examine_attribute (onerel , i , NULL );
357
358
if (vacattrstats [tcnt ] != NULL )
358
359
tcnt ++ ;
359
360
}
@@ -407,21 +408,8 @@ do_analyze_rel(Relation onerel, VacuumStmt *vacstmt,
407
408
elog (ERROR , "too few entries in indexprs list" );
408
409
indexkey = (Node * ) lfirst (indexpr_item );
409
410
indexpr_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
-
423
411
thisdata -> vacattrstats [tcnt ] =
424
- examine_attribute (Irel [ind ], i + 1 );
412
+ examine_attribute (Irel [ind ], i + 1 , indexkey );
425
413
if (thisdata -> vacattrstats [tcnt ] != NULL )
426
414
{
427
415
tcnt ++ ;
@@ -802,9 +790,12 @@ compute_index_stats(Relation onerel, double totalrows,
802
790
*
803
791
* Determine whether the column is analyzable; if so, create and initialize
804
792
* 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.
805
796
*/
806
797
static VacAttrStats *
807
- examine_attribute (Relation onerel , int attnum )
798
+ examine_attribute (Relation onerel , int attnum , Node * index_expr )
808
799
{
809
800
Form_pg_attribute attr = onerel -> rd_att -> attrs [attnum - 1 ];
810
801
HeapTuple typtuple ;
@@ -827,9 +818,30 @@ examine_attribute(Relation onerel, int attnum)
827
818
stats = (VacAttrStats * ) palloc0 (sizeof (VacAttrStats ));
828
819
stats -> attr = (Form_pg_attribute ) palloc (ATTRIBUTE_FIXED_PART_SIZE );
829
820
memcpy (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 ));
831
843
if (!HeapTupleIsValid (typtuple ))
832
- elog (ERROR , "cache lookup failed for type %u" , attr -> atttypid );
844
+ elog (ERROR , "cache lookup failed for type %u" , stats -> attrtypid );
833
845
stats -> attrtype = (Form_pg_type ) palloc (sizeof (FormData_pg_type ));
834
846
memcpy (stats -> attrtype , GETSTRUCT (typtuple ), sizeof (FormData_pg_type ));
835
847
ReleaseSysCache (typtuple );
@@ -838,12 +850,12 @@ examine_attribute(Relation onerel, int attnum)
838
850
839
851
/*
840
852
* The fields describing the stats->stavalues[n] element types default to
841
- * the type of the field being analyzed, but the type-specific typanalyze
853
+ * the type of the data being analyzed, but the type-specific typanalyze
842
854
* function can change them if it wants to store something else.
843
855
*/
844
856
for (i = 0 ; i < STATISTIC_NUM_SLOTS ; i ++ )
845
857
{
846
- stats -> statypid [i ] = stats -> attr -> atttypid ;
858
+ stats -> statypid [i ] = stats -> attrtypid ;
847
859
stats -> statyplen [i ] = stats -> attrtype -> typlen ;
848
860
stats -> statypbyval [i ] = stats -> attrtype -> typbyval ;
849
861
stats -> statypalign [i ] = stats -> attrtype -> typalign ;
@@ -1780,7 +1792,7 @@ std_typanalyze(VacAttrStats *stats)
1780
1792
attr -> attstattarget = default_statistics_target ;
1781
1793
1782
1794
/* Look for default "<" and "=" operators for column's type */
1783
- get_sort_group_operators (attr -> atttypid ,
1795
+ get_sort_group_operators (stats -> attrtypid ,
1784
1796
false, false, false,
1785
1797
& ltopr , & eqopr , NULL );
1786
1798
@@ -1860,10 +1872,10 @@ compute_minimal_stats(VacAttrStatsP stats,
1860
1872
int nonnull_cnt = 0 ;
1861
1873
int toowide_cnt = 0 ;
1862
1874
double 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 );
1867
1879
FmgrInfo f_cmpeq ;
1868
1880
typedef struct
1869
1881
{
@@ -2126,8 +2138,8 @@ compute_minimal_stats(VacAttrStatsP stats,
2126
2138
for (i = 0 ; i < num_mcv ; i ++ )
2127
2139
{
2128
2140
mcv_values [i ] = datumCopy (track [i ].value ,
2129
- stats -> attr -> attbyval ,
2130
- stats -> attr -> attlen );
2141
+ stats -> attrtype -> typbyval ,
2142
+ stats -> attrtype -> typlen );
2131
2143
mcv_freqs [i ] = (double ) track [i ].count / (double ) samplerows ;
2132
2144
}
2133
2145
MemoryContextSwitchTo (old_context );
@@ -2184,10 +2196,10 @@ compute_scalar_stats(VacAttrStatsP stats,
2184
2196
int nonnull_cnt = 0 ;
2185
2197
int toowide_cnt = 0 ;
2186
2198
double 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 );
2191
2203
double corr_xysum ;
2192
2204
Oid cmpFn ;
2193
2205
int cmpFlags ;
@@ -2476,8 +2488,8 @@ compute_scalar_stats(VacAttrStatsP stats,
2476
2488
for (i = 0 ; i < num_mcv ; i ++ )
2477
2489
{
2478
2490
mcv_values [i ] = datumCopy (values [track [i ].first ].value ,
2479
- stats -> attr -> attbyval ,
2480
- stats -> attr -> attlen );
2491
+ stats -> attrtype -> typbyval ,
2492
+ stats -> attrtype -> typlen );
2481
2493
mcv_freqs [i ] = (double ) track [i ].count / (double ) samplerows ;
2482
2494
}
2483
2495
MemoryContextSwitchTo (old_context );
@@ -2583,8 +2595,8 @@ compute_scalar_stats(VacAttrStatsP stats,
2583
2595
for (i = 0 ; i < num_hist ; i ++ )
2584
2596
{
2585
2597
hist_values [i ] = datumCopy (values [pos ].value ,
2586
- stats -> attr -> attbyval ,
2587
- stats -> attr -> attlen );
2598
+ stats -> attrtype -> typbyval ,
2599
+ stats -> attrtype -> typlen );
2588
2600
pos += delta ;
2589
2601
posfrac += deltafrac ;
2590
2602
if (posfrac >= (num_hist - 1 ))
0 commit comments