aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/utils/adt/orderedsetaggs.c34
-rw-r--r--src/test/regress/expected/aggregates.out8
-rw-r--r--src/test/regress/sql/aggregates.sql2
3 files changed, 26 insertions, 18 deletions
diff --git a/src/backend/utils/adt/orderedsetaggs.c b/src/backend/utils/adt/orderedsetaggs.c
index 135a14b0228..a290140e9c2 100644
--- a/src/backend/utils/adt/orderedsetaggs.c
+++ b/src/backend/utils/adt/orderedsetaggs.c
@@ -904,42 +904,50 @@ percentile_cont_multi_final_common(FunctionCallInfo fcinfo,
for (; i < num_percentiles; i++)
{
- int64 target_row = pct_info[i].first_row;
- bool need_lerp = (pct_info[i].second_row > target_row);
+ int64 first_row = pct_info[i].first_row;
+ int64 second_row = pct_info[i].second_row;
int idx = pct_info[i].idx;
- /* Advance to first_row, if not already there */
- if (target_row > rownum)
+ /*
+ * Advance to first_row, if not already there. Note that we might
+ * already have rownum beyond first_row, in which case first_val
+ * is already correct. (This occurs when interpolating between
+ * the same two input rows as for the previous percentile.)
+ */
+ if (first_row > rownum)
{
- if (!tuplesort_skiptuples(osastate->sortstate, target_row - rownum - 1, true))
+ if (!tuplesort_skiptuples(osastate->sortstate, first_row - rownum - 1, true))
elog(ERROR, "missing row in percentile_cont");
if (!tuplesort_getdatum(osastate->sortstate, true, &first_val, &isnull) || isnull)
elog(ERROR, "missing row in percentile_cont");
- rownum = target_row;
+ rownum = first_row;
+ /* Always advance second_val to be latest input value */
+ second_val = first_val;
}
- else
+ else if (first_row == rownum)
{
/*
- * We are already at the target row, so we must previously
- * have read its value into second_val.
+ * We are already at the desired row, so we must previously
+ * have read its value into second_val (and perhaps first_val
+ * as well, but this assignment is harmless in that case).
*/
first_val = second_val;
}
/* Fetch second_row if needed */
- if (need_lerp)
+ if (second_row > rownum)
{
if (!tuplesort_getdatum(osastate->sortstate, true, &second_val, &isnull) || isnull)
elog(ERROR, "missing row in percentile_cont");
rownum++;
}
- else
- second_val = first_val;
+ /* We should now certainly be on second_row exactly */
+ Assert(second_row == rownum);
/* Compute appropriate result */
- if (need_lerp)
+ if (second_row > first_row)
result_datum[idx] = lerpfunc(first_val, second_val,
pct_info[i].proportion);
else
diff --git a/src/test/regress/expected/aggregates.out b/src/test/regress/expected/aggregates.out
index 58df85470a6..40f5398b72c 100644
--- a/src/test/regress/expected/aggregates.out
+++ b/src/test/regress/expected/aggregates.out
@@ -1423,11 +1423,11 @@ from tenk1;
{{NULL,999,499},{749,249,NULL}}
(1 row)
-select percentile_cont(array[0,1,0.25,0.75,0.5,1]) within group (order by x)
+select percentile_cont(array[0,1,0.25,0.75,0.5,1,0.3,0.32,0.35,0.38,0.4]) within group (order by x)
from generate_series(1,6) x;
- percentile_cont
------------------------
- {1,6,2.25,4.75,3.5,6}
+ percentile_cont
+------------------------------------------
+ {1,6,2.25,4.75,3.5,6,2.5,2.6,2.75,2.9,3}
(1 row)
select ten, mode() within group (order by string4) from tenk1 group by ten;
diff --git a/src/test/regress/sql/aggregates.sql b/src/test/regress/sql/aggregates.sql
index 8096a6ffbec..a84327d24cc 100644
--- a/src/test/regress/sql/aggregates.sql
+++ b/src/test/regress/sql/aggregates.sql
@@ -533,7 +533,7 @@ select percentile_cont(array[0,0.25,0.5,0.75,1]) within group (order by thousand
from tenk1;
select percentile_disc(array[[null,1,0.5],[0.75,0.25,null]]) within group (order by thousand)
from tenk1;
-select percentile_cont(array[0,1,0.25,0.75,0.5,1]) within group (order by x)
+select percentile_cont(array[0,1,0.25,0.75,0.5,1,0.3,0.32,0.35,0.38,0.4]) within group (order by x)
from generate_series(1,6) x;
select ten, mode() within group (order by string4) from tenk1 group by ten;