Handle negative values in saturating sub and add

The functions for saturating addition and subtraction of time values
assumed positive intervals as input. This change generalizes the code
to also handle negative intervals being added or subtracted.
This commit is contained in:
Erik Nordström 2020-10-14 17:46:46 +02:00 committed by Erik Nordström
parent ce6387aa90
commit 5564ad8c6c
2 changed files with 48 additions and 25 deletions

View File

@ -419,6 +419,15 @@ ts_time_get_nobegin(Oid timetype)
return ts_time_get_nobegin(coerce_to_time_type(timetype));
}
static int64
ts_time_get_nobegin_or_min(Oid timetype)
{
if (IS_TIMESTAMP_TYPE(timetype))
return ts_time_get_nobegin(timetype);
return ts_time_get_min(timetype);
}
int64
ts_time_get_noend(Oid timetype)
{
@ -460,18 +469,11 @@ ts_time_get_noend_or_max(Oid timetype)
int64
ts_time_saturating_add(int64 timeval, int64 interval, Oid timetype)
{
if (IS_TIMESTAMP_TYPE(timetype))
{
if (timeval >= (ts_time_get_end(timetype) - interval))
return ts_time_get_noend(timetype);
}
else
{
int64 time_max = ts_time_get_max(timetype);
if (timeval > 0 && interval > 0 && timeval > (ts_time_get_max(timetype) - interval))
return ts_time_get_noend_or_max(timetype);
if (timeval > (time_max - interval))
return time_max;
}
if (timeval < 0 && interval < 0 && timeval < (ts_time_get_min(timetype) - interval))
return ts_time_get_nobegin_or_min(timetype);
return timeval + interval;
}
@ -487,18 +489,11 @@ ts_time_saturating_add(int64 timeval, int64 interval, Oid timetype)
int64
ts_time_saturating_sub(int64 timeval, int64 interval, Oid timetype)
{
if (IS_TIMESTAMP_TYPE(timetype))
{
if (timeval < (ts_time_get_min(timetype) + interval))
return ts_time_get_nobegin(timetype);
}
else
{
int64 time_min = ts_time_get_min(timetype);
if (timeval < 0 && interval > 0 && timeval < (ts_time_get_min(timetype) + interval))
return ts_time_get_nobegin_or_min(timetype);
if (timeval < (time_min + interval))
return time_min;
}
if (timeval > 0 && interval < 0 && timeval > (ts_time_get_max(timetype) + interval))
return ts_time_get_noend_or_max(timetype);
return timeval - interval;
}

View File

@ -295,11 +295,11 @@ ts_test_time_utils(PG_FUNCTION_ARGS)
ts_time_get_max(INT8OID));
TestAssertInt64Eq(ts_time_saturating_add(ts_time_get_max(DATEOID), 1, DATEOID),
ts_time_get_noend(DATEOID));
TestAssertInt64Eq(ts_time_saturating_add(ts_time_get_end(DATEOID) - 1, 1, DATEOID),
TestAssertInt64Eq(ts_time_saturating_add(ts_time_get_max(DATEOID), 1, DATEOID),
ts_time_get_noend(DATEOID));
TestAssertInt64Eq(ts_time_saturating_add(ts_time_get_end(TIMESTAMPOID) - 1, 1, TIMESTAMPOID),
TestAssertInt64Eq(ts_time_saturating_add(ts_time_get_max(TIMESTAMPOID), 1, TIMESTAMPOID),
ts_time_get_noend(TIMESTAMPOID));
TestAssertInt64Eq(ts_time_saturating_add(ts_time_get_end(TIMESTAMPTZOID) - 1, 1, TIMESTAMPOID),
TestAssertInt64Eq(ts_time_saturating_add(ts_time_get_max(TIMESTAMPTZOID), 1, TIMESTAMPOID),
ts_time_get_noend(TIMESTAMPOID));
TestAssertInt64Eq(ts_time_saturating_add(ts_time_get_end(DATEOID) - 2, 1, DATEOID),
ts_time_get_max(DATEOID));
@ -308,6 +308,21 @@ ts_test_time_utils(PG_FUNCTION_ARGS)
TestAssertInt64Eq(ts_time_saturating_add(ts_time_get_end(TIMESTAMPTZOID) - 2, 1, TIMESTAMPOID),
ts_time_get_max(TIMESTAMPOID));
TestAssertInt64Eq(ts_time_saturating_add(ts_time_get_min(INT2OID), -1, INT2OID),
ts_time_get_min(INT2OID));
TestAssertInt64Eq(ts_time_saturating_add(ts_time_get_min(INT4OID), -1, INT4OID),
ts_time_get_min(INT4OID));
TestAssertInt64Eq(ts_time_saturating_add(ts_time_get_min(INT8OID), -1, INT8OID),
ts_time_get_min(INT8OID));
TestAssertInt64Eq(ts_time_saturating_add(ts_time_get_min(DATEOID), -1, DATEOID),
ts_time_get_nobegin(DATEOID));
TestAssertInt64Eq(ts_time_saturating_add(ts_time_get_min(DATEOID), -1, DATEOID),
ts_time_get_nobegin(DATEOID));
TestAssertInt64Eq(ts_time_saturating_add(ts_time_get_min(TIMESTAMPOID), -1, TIMESTAMPOID),
ts_time_get_nobegin(TIMESTAMPOID));
TestAssertInt64Eq(ts_time_saturating_add(ts_time_get_min(TIMESTAMPTZOID), -1, TIMESTAMPOID),
ts_time_get_nobegin(TIMESTAMPOID));
/* Test saturating subtraction */
TestAssertInt64Eq(ts_time_saturating_sub(ts_time_get_min(INT2OID), 1, INT2OID),
ts_time_get_min(INT2OID));
@ -330,5 +345,18 @@ ts_test_time_utils(PG_FUNCTION_ARGS)
TIMESTAMPTZOID),
ts_time_get_min(TIMESTAMPTZOID));
TestAssertInt64Eq(ts_time_saturating_sub(ts_time_get_max(INT2OID), -1, INT2OID),
ts_time_get_max(INT2OID));
TestAssertInt64Eq(ts_time_saturating_sub(ts_time_get_max(INT4OID), -1, INT4OID),
ts_time_get_max(INT4OID));
TestAssertInt64Eq(ts_time_saturating_sub(ts_time_get_max(INT8OID), -1, INT8OID),
ts_time_get_max(INT8OID));
TestAssertInt64Eq(ts_time_saturating_sub(ts_time_get_max(DATEOID), -1, DATEOID),
ts_time_get_noend(DATEOID));
TestAssertInt64Eq(ts_time_saturating_sub(ts_time_get_max(TIMESTAMPOID), -1, TIMESTAMPOID),
ts_time_get_noend(TIMESTAMPOID));
TestAssertInt64Eq(ts_time_saturating_sub(ts_time_get_max(TIMESTAMPTZOID), -1, TIMESTAMPTZOID),
ts_time_get_noend(TIMESTAMPTZOID));
PG_RETURN_VOID();
}