use super::*;
pub(super) fn value_cmp_for_min_max(a: &Value, b: &Value) -> core::cmp::Ordering {
use core::cmp::Ordering;
let a_int = match a {
Value::SmallInt(x) => Some(i64::from(*x)),
Value::Int(x) => Some(i64::from(*x)),
Value::BigInt(x) => Some(*x),
_ => None,
};
let b_int = match b {
Value::SmallInt(x) => Some(i64::from(*x)),
Value::Int(x) => Some(i64::from(*x)),
Value::BigInt(x) => Some(*x),
_ => None,
};
if let (Some(av), Some(bv)) = (a_int, b_int) {
return av.cmp(&bv);
}
let a_f = value_to_f64(a);
let b_f = value_to_f64(b);
if let (Some(av), Some(bv)) = (a_f, b_f) {
return av.partial_cmp(&bv).unwrap_or(Ordering::Equal);
}
match (a, b) {
(Value::Text(av), Value::Text(bv)) => av.cmp(bv),
(Value::Bytes(av), Value::Bytes(bv)) => av.cmp(bv),
_ => Ordering::Equal,
}
}
pub(super) fn value_to_f64(v: &Value) -> Option<f64> {
match v {
Value::Float(x) => Some(*x),
Value::SmallInt(x) => Some(f64::from(*x)),
Value::Int(x) => Some(f64::from(*x)),
Value::BigInt(x) => Some(*x as f64),
Value::Numeric { scaled, scale } => {
Some((*scaled as f64) / f64_powi(10.0, i32::from(*scale)))
}
_ => None,
}
}
pub(super) fn values_equal_for_nullif(a: &Value, b: &Value) -> bool {
if a == b {
return true;
}
let a_int = match a {
Value::SmallInt(x) => Some(i64::from(*x)),
Value::Int(x) => Some(i64::from(*x)),
Value::BigInt(x) => Some(*x),
_ => None,
};
let b_int = match b {
Value::SmallInt(x) => Some(i64::from(*x)),
Value::Int(x) => Some(i64::from(*x)),
Value::BigInt(x) => Some(*x),
_ => None,
};
if let (Some(a), Some(b)) = (a_int, b_int) {
return a == b;
}
let a_f = match a {
Value::Float(x) => Some(*x),
Value::SmallInt(x) => Some(f64::from(*x)),
Value::Int(x) => Some(f64::from(*x)),
Value::BigInt(x) => Some(*x as f64),
Value::Numeric { scaled, scale } => {
Some((*scaled as f64) / f64_powi(10.0, i32::from(*scale)))
}
_ => None,
};
let b_f = match b {
Value::Float(x) => Some(*x),
Value::SmallInt(x) => Some(f64::from(*x)),
Value::Int(x) => Some(f64::from(*x)),
Value::BigInt(x) => Some(*x as f64),
Value::Numeric { scaled, scale } => {
Some((*scaled as f64) / f64_powi(10.0, i32::from(*scale)))
}
_ => None,
};
if let (Some(a), Some(b)) = (a_f, b_f) {
return a == b;
}
false
}
pub fn gen_random_uuid_bytes() -> [u8; 16] {
let mut out = [0u8; 16];
let hi = prng_next_u64().to_be_bytes();
let lo = prng_next_u64().to_be_bytes();
out[..8].copy_from_slice(&hi);
out[8..].copy_from_slice(&lo);
out[6] = (out[6] & 0x0f) | 0x40;
out[8] = (out[8] & 0x3f) | 0x80;
out
}
pub(super) fn value_to_text(v: &Value) -> String {
match v {
Value::SmallInt(n) => format!("{n}"),
Value::Int(n) => format!("{n}"),
Value::BigInt(n) => format!("{n}"),
Value::Float(x) => format!("{x}"),
Value::Text(s) | Value::Json(s) => s.clone(),
Value::Bool(b) => (if *b { "true" } else { "false" }).into(),
Value::Vector(v) => {
let cells: Vec<String> = v.iter().map(|x| format!("{x}")).collect();
format!("[{}]", cells.join(", "))
}
Value::Sq8Vector(q) => {
let cells: Vec<String> = spg_storage::quantize::dequantize(q)
.iter()
.map(|x| format!("{x}"))
.collect();
format!("[{}]", cells.join(", "))
}
Value::HalfVector(h) => {
let cells: Vec<String> = h.to_f32_vec().iter().map(|x| format!("{x}")).collect();
format!("[{}]", cells.join(", "))
}
Value::Numeric { scaled, scale } => format_numeric(*scaled, *scale),
Value::Date(d) => format_date(*d),
Value::Timestamp(t) => format_timestamp(*t),
Value::Interval { months, micros } => format_interval(*months, *micros),
Value::Null => "NULL".into(),
Value::Bytes(b) => format_bytea_hex(b),
Value::TextArray(items) => format_text_array(items),
Value::IntArray(items) => format_int_array(items),
Value::BigIntArray(items) => format_bigint_array(items),
Value::TsVector(lexs) => format_tsvector(lexs),
Value::TsQuery(ast) => format_tsquery(ast),
Value::Uuid(b) => spg_storage::format_uuid(b),
Value::Time(us) => format_time(*us),
Value::TimeTz { us, offset_secs } => format_timetz(*us, *offset_secs),
Value::Year(y) => format!("{y:04}"),
Value::Money(c) => format_money(*c),
Value::Range { .. } => crate::conversions::format_range_text(v),
Value::Hstore(pairs) => crate::conversions::format_hstore_text(pairs),
Value::IntArray2D(rows) => crate::conversions::format_int_2d_text_pub(rows),
Value::BigIntArray2D(rows) => crate::conversions::format_bigint_2d_text_pub(rows),
Value::TextArray2D(rows) => crate::conversions::format_text_2d_text_pub(rows),
_ => format!("{v:?}"),
}
}