Skip to main content

cratestack_sql/values/
sql_value.rs

1use cratestack_core::Value;
2
3#[derive(Debug, Clone, PartialEq)]
4pub enum SqlValue {
5    Bool(bool),
6    Int(i64),
7    Float(f64),
8    String(String),
9    Bytes(Vec<u8>),
10    Uuid(uuid::Uuid),
11    DateTime(chrono::DateTime<chrono::Utc>),
12    Json(Value),
13    Decimal(cratestack_core::Decimal),
14    NullBool,
15    NullInt,
16    NullFloat,
17    NullString,
18    NullBytes,
19    NullUuid,
20    NullDateTime,
21    NullJson,
22    NullDecimal,
23}
24
25#[derive(Debug, Clone, PartialEq)]
26pub enum FilterValue {
27    None,
28    Single(SqlValue),
29    Many(Vec<SqlValue>),
30}
31
32#[derive(Debug, Clone, PartialEq)]
33pub struct SqlColumnValue {
34    pub column: &'static str,
35    pub value: SqlValue,
36}
37
38/// Detect the first duplicate value in a list of `SqlValue`s, used for
39/// batch_upsert input deduplication. Linear-scan with `PartialEq` rather
40/// than the hashed variant in `cratestack-core` because `SqlValue::Float`
41/// and `SqlValue::Decimal` don't admit a sound `Hash` impl.
42///
43/// At the documented batch cap (≤ 1000 items) the O(N²) cost is on the
44/// order of a million `PartialEq` comparisons, which dominates nothing
45/// next to a single round-trip to Postgres. Returns `(first_index,
46/// duplicate_index)` on collision, matching `cratestack_core::find_duplicate_position`.
47pub fn find_duplicate_sql_value(values: &[SqlValue]) -> Option<(usize, usize)> {
48    for (index, value) in values.iter().enumerate() {
49        if let Some(earlier) = values[..index].iter().position(|prior| prior == value) {
50            return Some((earlier, index));
51        }
52    }
53    None
54}