Skip to content

Commit 12fafe4

Browse files
author
hackorum
committed
Apply guard-against-interval-sign-changes-wip.patch
1 parent 0ec3f04 commit 12fafe4

1 file changed

Lines changed: 27 additions & 10 deletions

File tree

src/backend/utils/adt/timestamp.c

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6723,6 +6723,7 @@ generate_series_timestamp(PG_FUNCTION_ARGS)
67236723
FuncCallContext *funcctx;
67246724
generate_series_timestamp_fctx *fctx;
67256725
Timestamp result;
6726+
Timestamp nextval = 0;
67266727

67276728
/* stuff done only on the first call of the function */
67286729
if (SRF_IS_FIRSTCALL())
@@ -6751,18 +6752,25 @@ generate_series_timestamp(PG_FUNCTION_ARGS)
67516752
fctx->finish = finish;
67526753
fctx->step = *step;
67536754

6754-
/* Determine sign of the interval */
6755-
fctx->step_sign = interval_sign(&fctx->step);
6756-
6757-
if (fctx->step_sign == 0)
6755+
if (INTERVAL_NOT_FINITE((&fctx->step)))
67586756
ereport(ERROR,
67596757
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6760-
errmsg("step size cannot equal zero")));
6758+
errmsg("step size cannot be infinite")));
67616759

6762-
if (INTERVAL_NOT_FINITE((&fctx->step)))
6760+
/*
6761+
* Compute the next series value so that we can identify the step
6762+
* direction. This seems more reliable than trusting interval_sign().
6763+
*/
6764+
nextval =
6765+
DatumGetTimestamp(DirectFunctionCall2(timestamp_pl_interval,
6766+
TimestampGetDatum(start),
6767+
PointerGetDatum(&fctx->step)));
6768+
fctx->step_sign = timestamp_cmp_internal(nextval, start);
6769+
6770+
if (fctx->step_sign == 0)
67636771
ereport(ERROR,
67646772
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6765-
errmsg("step size cannot be infinite")));
6773+
errmsg("step size cannot equal zero")));
67666774

67676775
funcctx->user_fctx = fctx;
67686776
MemoryContextSwitchTo(oldcontext);
@@ -6782,9 +6790,18 @@ generate_series_timestamp(PG_FUNCTION_ARGS)
67826790
timestamp_cmp_internal(result, fctx->finish) >= 0)
67836791
{
67846792
/* increment current in preparation for next iteration */
6785-
fctx->current = DatumGetTimestamp(DirectFunctionCall2(timestamp_pl_interval,
6786-
TimestampGetDatum(fctx->current),
6787-
PointerGetDatum(&fctx->step)));
6793+
if (nextval)
6794+
fctx->current = nextval; /* already calculated it */
6795+
else
6796+
fctx->current =
6797+
DatumGetTimestamp(DirectFunctionCall2(timestamp_pl_interval,
6798+
TimestampGetDatum(result),
6799+
PointerGetDatum(&fctx->step)));
6800+
/* check for directional instability */
6801+
if (fctx->step_sign != timestamp_cmp_internal(fctx->current, result))
6802+
ereport(ERROR,
6803+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
6804+
errmsg("step size changed sign")));
67886805

67896806
/* do when there is more left to send */
67906807
SRF_RETURN_NEXT(funcctx, TimestampGetDatum(result));

0 commit comments

Comments
 (0)