Skip to content

Commit 4031e82

Browse files
committed
x
1 parent 6505183 commit 4031e82

10 files changed

Lines changed: 1914 additions & 374 deletions

File tree

src/common/statistics/src/datum.rs

Lines changed: 117 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ use databend_common_exception::ErrorCode;
2020

2121
pub type F64 = OrderedFloat<f64>;
2222

23+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
24+
pub enum DatumKind {
25+
Int,
26+
UInt,
27+
Float,
28+
Bytes,
29+
}
30+
2331
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
2432
pub enum Datum {
2533
Bool(bool),
@@ -34,14 +42,6 @@ impl Datum {
3442
matches!(self, Datum::Bytes(_))
3543
}
3644

37-
pub fn cast_float(self) -> Self {
38-
match self {
39-
Datum::Int(v) => Datum::Float(F64::from(v as f64)),
40-
Datum::UInt(v) => Datum::Float(F64::from(v as f64)),
41-
_ => self,
42-
}
43-
}
44-
4545
pub fn as_double(&self) -> Result<f64, ErrorCode> {
4646
match self {
4747
Datum::Bool(v) => Ok(*v as u8 as f64),
@@ -122,6 +122,104 @@ impl Datum {
122122
matches!(self, Datum::Int(_) | Datum::UInt(_) | Datum::Float(_))
123123
}
124124

125+
pub fn kind(&self) -> Option<DatumKind> {
126+
match self {
127+
Datum::Int(_) => Some(DatumKind::Int),
128+
Datum::UInt(_) => Some(DatumKind::UInt),
129+
Datum::Float(_) => Some(DatumKind::Float),
130+
Datum::Bytes(_) => Some(DatumKind::Bytes),
131+
Datum::Bool(_) => None,
132+
}
133+
}
134+
135+
pub fn normalize_to_kind(&self, kind: DatumKind) -> Option<Datum> {
136+
match kind {
137+
DatumKind::Int => self.as_i64().map(Datum::Int),
138+
DatumKind::UInt => self.as_u64().map(Datum::UInt),
139+
DatumKind::Float => self.as_double().ok().map(F64::from).map(Datum::Float),
140+
DatumKind::Bytes => match self {
141+
Datum::Bytes(value) => Some(Datum::Bytes(value.clone())),
142+
_ => None,
143+
},
144+
}
145+
}
146+
147+
pub fn lower_bound_to_kind(&self, kind: DatumKind) -> Option<Datum> {
148+
match kind {
149+
DatumKind::Int => self.lower_bound_as_i64().map(Datum::Int),
150+
DatumKind::UInt => self.lower_bound_as_u64().map(Datum::UInt),
151+
_ => self.normalize_to_kind(kind),
152+
}
153+
}
154+
155+
pub fn upper_bound_to_kind(&self, kind: DatumKind) -> Option<Datum> {
156+
match kind {
157+
DatumKind::Int => self.upper_bound_as_i64().map(Datum::Int),
158+
DatumKind::UInt => self.upper_bound_as_u64().map(Datum::UInt),
159+
_ => self.normalize_to_kind(kind),
160+
}
161+
}
162+
163+
pub fn as_i64(&self) -> Option<i64> {
164+
match self {
165+
Datum::Int(value) => Some(*value),
166+
Datum::UInt(value) => i64::try_from(*value).ok(),
167+
Datum::Float(value) => {
168+
let value = value.into_inner();
169+
(value.is_finite()
170+
&& value.fract() == 0.0
171+
&& value >= i64::MIN as f64
172+
&& value <= i64::MAX as f64)
173+
.then_some(value as i64)
174+
}
175+
_ => None,
176+
}
177+
}
178+
179+
pub fn as_u64(&self) -> Option<u64> {
180+
match self {
181+
Datum::UInt(value) => Some(*value),
182+
Datum::Int(value) => u64::try_from(*value).ok(),
183+
Datum::Float(value) => {
184+
let value = value.into_inner();
185+
(value.is_finite()
186+
&& value.fract() == 0.0
187+
&& value >= 0.0
188+
&& value <= u64::MAX as f64)
189+
.then_some(value as u64)
190+
}
191+
_ => None,
192+
}
193+
}
194+
195+
fn lower_bound_as_i64(&self) -> Option<i64> {
196+
match self {
197+
Datum::Float(value) => float_to_i64_bound(value.into_inner(), f64::ceil),
198+
_ => self.as_i64(),
199+
}
200+
}
201+
202+
fn upper_bound_as_i64(&self) -> Option<i64> {
203+
match self {
204+
Datum::Float(value) => float_to_i64_bound(value.into_inner(), f64::floor),
205+
_ => self.as_i64(),
206+
}
207+
}
208+
209+
fn lower_bound_as_u64(&self) -> Option<u64> {
210+
match self {
211+
Datum::Float(value) => float_to_u64_bound(value.into_inner(), f64::ceil),
212+
_ => self.as_u64(),
213+
}
214+
}
215+
216+
fn upper_bound_as_u64(&self) -> Option<u64> {
217+
match self {
218+
Datum::Float(value) => float_to_u64_bound(value.into_inner(), f64::floor),
219+
_ => self.as_u64(),
220+
}
221+
}
222+
125223
pub fn type_name(&self) -> &'static str {
126224
match self {
127225
Datum::Bool(_) => "Boolean",
@@ -159,3 +257,14 @@ impl Datum {
159257
}
160258
}
161259
}
260+
261+
fn float_to_i64_bound(value: f64, round: fn(f64) -> f64) -> Option<i64> {
262+
let value = round(value);
263+
(value.is_finite() && value >= i64::MIN as f64 && value <= i64::MAX as f64)
264+
.then_some(value as i64)
265+
}
266+
267+
fn float_to_u64_bound(value: f64, round: fn(f64) -> f64) -> Option<u64> {
268+
let value = round(value);
269+
(value.is_finite() && value >= 0.0 && value <= u64::MAX as f64).then_some(value as u64)
270+
}

0 commit comments

Comments
 (0)