struct IntervalCmpValue(i128);
Expand description
https://github.com/postgres/postgres/blob/REL_15_2/src/backend/utils/adt/timestamp.c#L2384
Do NOT make this pub
as the assumption of 1 month = 30 days and 1 day = 24 hours does not
always hold in other places.
Given this equality definition in PostgreSQL, different interval values can be considered equal, forming equivalence classes. For example:
- ‘-45 days’ == ‘-1 months -15 days’ == ‘1 months -75 days’
- ‘-2147483646 months -210 days’ == ‘-2147483648 months -150 days’ == ‘-2075900865 months -2147483640 days’
To hash and memcompare them, we need to pick a representative for each equivalence class, and
then map all values from the same equivalence class to the same representative. There are 3
choices (may be more):
(a) an i128
of total usecs
, with months
and days
transformed into usecs
;
(b) the justified interval, as defined by PostgreSQL justify_interval
;
(c) the alternate representative interval that maximizes abs
of smaller units;
For simplicity we will assume there are only months
and days
and ignore usecs
below.
The justified interval is more human friendly. It requires all units to have the same sign, and
that 0 <= abs(usecs) < USECS_PER_DAY && 0 <= abs(days) < 30
. However, it may overflow. In the
2 examples above, ‘-1 months -15 days’ is the justified interval of the first equivalence class,
but there is no justified interval in the second one. It would be ‘-2147483653 months’ but this
overflows i32
. A lot of bits are wasted in a justified interval because days
is using
i32
for -29..=29
only.
The alternate representative interval aims to avoid this overflow. It still requires all units
to have the same sign, but maximizes abs
of smaller unit rather than limit it to 29
. The
alternate representative of the 2 examples above are ‘-45 days’ and ‘-2075900865 months
-2147483640 days’. The alternate representative interval always exists.
For serialize, we could use any of 3, with a workaround of using (i33, i6, i38) rather than
(i32, i32, i64) to avoid overflow of the justified interval. We chose the usecs: i128
option.
For deserialize, we attempt justified interval first and fallback to alternate. This could give human friendly results in common cases and still guarantee no overflow, as long as the bytes were serialized properly.
Note the alternate representative interval does not exist in PostgreSQL as they do not
deserialize from IntervalCmpValue
.
Tuple Fields§
§0: i128
Implementations§
source§impl IntervalCmpValue
impl IntervalCmpValue
sourcefn as_justified(&self) -> Option<Interval>
fn as_justified(&self) -> Option<Interval>
Recover the justified interval from this equivalence class, if it exists.
sourcefn as_alternate(&self) -> Option<Interval>
fn as_alternate(&self) -> Option<Interval>
Recover the alternate representative interval from this equivalence class.
It always exists unless the encoding is invalid. See IntervalCmpValue
for details.
Trait Implementations§
source§impl From<Interval> for IntervalCmpValue
impl From<Interval> for IntervalCmpValue
source§impl Hash for IntervalCmpValue
impl Hash for IntervalCmpValue
source§impl Ord for IntervalCmpValue
impl Ord for IntervalCmpValue
source§fn cmp(&self, other: &IntervalCmpValue) -> Ordering
fn cmp(&self, other: &IntervalCmpValue) -> Ordering
1.21.0 · source§fn max(self, other: Self) -> Selfwhere
Self: Sized,
fn max(self, other: Self) -> Selfwhere
Self: Sized,
source§impl PartialEq for IntervalCmpValue
impl PartialEq for IntervalCmpValue
source§impl PartialOrd for IntervalCmpValue
impl PartialOrd for IntervalCmpValue
impl Eq for IntervalCmpValue
impl StructuralPartialEq for IntervalCmpValue
Auto Trait Implementations§
impl Freeze for IntervalCmpValue
impl RefUnwindSafe for IntervalCmpValue
impl Send for IntervalCmpValue
impl Sync for IntervalCmpValue
impl Unpin for IntervalCmpValue
impl UnwindSafe for IntervalCmpValue
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<Q, K> Comparable<K> for Q
impl<Q, K> Comparable<K> for Q
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key
and return true
if they are equal.source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key
and return true
if they are equal.§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
§impl<T> FutureExt for T
impl<T> FutureExt for T
§fn with_context(self, otel_cx: Context) -> WithContext<Self>
fn with_context(self, otel_cx: Context) -> WithContext<Self>
§fn with_current_context(self) -> WithContext<Self>
fn with_current_context(self) -> WithContext<Self>
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
source§impl<T> Instrument for T
impl<T> Instrument for T
source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
source§impl<T> IntoEither for T
impl<T> IntoEither for T
source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moresource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moresource§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T
in a tonic::Request
§impl<T> IntoResult<T> for T
impl<T> IntoResult<T> for T
type Err = Infallible
fn into_result(self) -> Result<T, <T as IntoResult<T>>::Err>
source§impl<M> MetricVecRelabelExt for M
impl<M> MetricVecRelabelExt for M
source§fn relabel(
self,
metric_level: MetricLevel,
relabel_threshold: MetricLevel,
) -> RelabeledMetricVec<M>
fn relabel( self, metric_level: MetricLevel, relabel_threshold: MetricLevel, ) -> RelabeledMetricVec<M>
RelabeledMetricVec::with_metric_level
.source§fn relabel_n(
self,
metric_level: MetricLevel,
relabel_threshold: MetricLevel,
relabel_num: usize,
) -> RelabeledMetricVec<M>
fn relabel_n( self, metric_level: MetricLevel, relabel_threshold: MetricLevel, relabel_num: usize, ) -> RelabeledMetricVec<M>
RelabeledMetricVec::with_metric_level_relabel_n
.source§fn relabel_debug_1(
self,
relabel_threshold: MetricLevel,
) -> RelabeledMetricVec<M>
fn relabel_debug_1( self, relabel_threshold: MetricLevel, ) -> RelabeledMetricVec<M>
RelabeledMetricVec::with_metric_level_relabel_n
with metric_level
set to
MetricLevel::Debug
and relabel_num
set to 1.