|
8 | 8 | * |
9 | 9 | * |
10 | 10 | * IDENTIFICATION |
11 | | - * $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.135 2009/03/31 22:12:46 tgl Exp $ |
| 11 | + * $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.136 2009/05/05 18:02:11 tgl Exp $ |
12 | 12 | * |
13 | 13 | *------------------------------------------------------------------------- |
14 | 14 | */ |
@@ -2260,6 +2260,10 @@ compute_scalar_stats(VacAttrStatsP stats, |
2260 | 2260 | MemoryContextold_context; |
2261 | 2261 | Datum*hist_values; |
2262 | 2262 | intnvals; |
| 2263 | +intpos, |
| 2264 | +posfrac, |
| 2265 | +delta, |
| 2266 | +deltafrac; |
2263 | 2267 |
|
2264 | 2268 | /* Sort the MCV items into position order to speed next loop */ |
2265 | 2269 | qsort((void*)track,num_mcv, |
@@ -2313,15 +2317,35 @@ compute_scalar_stats(VacAttrStatsP stats, |
2313 | 2317 | /* Must copy the target values into anl_context */ |
2314 | 2318 | old_context=MemoryContextSwitchTo(stats->anl_context); |
2315 | 2319 | hist_values= (Datum*)palloc(num_hist*sizeof(Datum)); |
| 2320 | + |
| 2321 | +/* |
| 2322 | + * The object of this loop is to copy the first and last values[] |
| 2323 | + * entries along with evenly-spaced values in between. So the |
| 2324 | + * i'th value is values[(i * (nvals - 1)) / (num_hist - 1)]. But |
| 2325 | + * computing that subscript directly risks integer overflow when |
| 2326 | + * the stats target is more than a couple thousand. Instead we |
| 2327 | + * add (nvals - 1) / (num_hist - 1) to pos at each step, tracking |
| 2328 | + * the integral and fractional parts of the sum separately. |
| 2329 | + */ |
| 2330 | +delta= (nvals-1) / (num_hist-1); |
| 2331 | +deltafrac= (nvals-1) % (num_hist-1); |
| 2332 | +pos=posfrac=0; |
| 2333 | + |
2316 | 2334 | for (i=0;i<num_hist;i++) |
2317 | 2335 | { |
2318 | | -intpos; |
2319 | | - |
2320 | | -pos= (i* (nvals-1)) / (num_hist-1); |
2321 | 2336 | hist_values[i]=datumCopy(values[pos].value, |
2322 | 2337 | stats->attr->attbyval, |
2323 | 2338 | stats->attr->attlen); |
| 2339 | +pos+=delta; |
| 2340 | +posfrac+=deltafrac; |
| 2341 | +if (posfrac >= (num_hist-1)) |
| 2342 | +{ |
| 2343 | +/* fractional part exceeds 1, carry to integer part */ |
| 2344 | +pos++; |
| 2345 | +posfrac-= (num_hist-1); |
| 2346 | +} |
2324 | 2347 | } |
| 2348 | + |
2325 | 2349 | MemoryContextSwitchTo(old_context); |
2326 | 2350 |
|
2327 | 2351 | stats->stakind[slot_idx]=STATISTIC_KIND_HISTOGRAM; |
|