|
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 | MemoryContext old_context;
|
2261 | 2261 | Datum *hist_values;
|
2262 | 2262 | int nvals;
|
| 2263 | + int pos, |
| 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 |
| - int pos; |
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;
|
|
0 commit comments