Skip to main content

spg_sqlx/types/
float.rs

1//! v7.16.0 — `Type` / `Encode` / `Decode` for f64 / f32 / FLOAT.
2
3use sqlx_core::decode::Decode;
4use sqlx_core::encode::{Encode, IsNull};
5use sqlx_core::error::BoxDynError;
6use sqlx_core::types::Type;
7
8use spg_embedded::ValueOwned as EngineValue;
9
10use crate::arguments::SpgArgumentValue;
11use crate::database::Spg;
12use crate::type_info::{Kind, SpgTypeInfo};
13use crate::value::SpgValueRef;
14
15impl Type<Spg> for f64 {
16    fn type_info() -> SpgTypeInfo {
17        SpgTypeInfo::of(Kind::Float)
18    }
19    fn compatible(ty: &SpgTypeInfo) -> bool {
20        matches!(ty.kind(), Kind::Float)
21    }
22}
23
24impl<'q> Encode<'q, Spg> for f64 {
25    fn encode_by_ref(&self, buf: &mut Vec<SpgArgumentValue<'q>>) -> Result<IsNull, BoxDynError> {
26        buf.push(SpgArgumentValue {
27            value: EngineValue::Float(*self),
28            type_info: Some(<f64 as Type<Spg>>::type_info()),
29            _phantom: core::marker::PhantomData,
30        });
31        Ok(IsNull::No)
32    }
33}
34
35impl<'r> Decode<'r, Spg> for f64 {
36    fn decode(value: SpgValueRef<'r>) -> Result<Self, BoxDynError> {
37        match value.engine() {
38            EngineValue::Float(x) => Ok(*x),
39            // v7.39 (round 269) — widening a REAL into f64 is lossless.
40            EngineValue::Real(x) => Ok(f64::from(*x)),
41            other => Err(format!("cannot decode {other:?} as f64 / FLOAT").into()),
42        }
43    }
44}
45
46impl Type<Spg> for f32 {
47    fn type_info() -> SpgTypeInfo {
48        SpgTypeInfo::of(Kind::Float)
49    }
50    fn compatible(ty: &SpgTypeInfo) -> bool {
51        matches!(ty.kind(), Kind::Float)
52    }
53}
54
55impl<'q> Encode<'q, Spg> for f32 {
56    fn encode_by_ref(&self, buf: &mut Vec<SpgArgumentValue<'q>>) -> Result<IsNull, BoxDynError> {
57        buf.push(SpgArgumentValue {
58            value: EngineValue::Float(f64::from(*self)),
59            type_info: Some(<f32 as Type<Spg>>::type_info()),
60            _phantom: core::marker::PhantomData,
61        });
62        Ok(IsNull::No)
63    }
64}
65
66impl<'r> Decode<'r, Spg> for f32 {
67    fn decode(value: SpgValueRef<'r>) -> Result<Self, BoxDynError> {
68        match value.engine() {
69            #[allow(clippy::cast_possible_truncation)]
70            EngineValue::Float(x) => Ok(*x as f32),
71            // v7.39 (round 269) — a REAL column is now genuinely 32-bit
72            // and yields Value::Real. Decoding it as f32 is the most
73            // natural pairing a customer can write, and it is exactly
74            // the one that had no arm here.
75            EngineValue::Real(x) => Ok(*x),
76            other => Err(format!("cannot decode {other:?} as f32 / FLOAT").into()),
77        }
78    }
79}