sqlx_exasol_impl/types/
float.rs

1use serde::Deserialize;
2use serde_json::Value;
3use sqlx_core::{
4    decode::Decode,
5    encode::{Encode, IsNull},
6    error::BoxDynError,
7    types::Type,
8};
9
10use crate::{
11    arguments::ExaBuffer,
12    database::Exasol,
13    type_info::{ExaDataType, ExaTypeInfo},
14    types::ExaHasArrayType,
15    value::ExaValueRef,
16};
17
18impl Type<Exasol> for f64 {
19    fn type_info() -> ExaTypeInfo {
20        ExaDataType::Double.into()
21    }
22}
23
24impl ExaHasArrayType for f64 {}
25
26impl Encode<'_, Exasol> for f64 {
27    fn encode_by_ref(&self, buf: &mut ExaBuffer) -> Result<IsNull, BoxDynError> {
28        // NaN is treated as NULL by Exasol.
29        // Infinity is not supported by Exasol but serde_json
30        // serializes it as NULL as well.
31        if self.is_finite() {
32            buf.append(self)?;
33            Ok(IsNull::No)
34        } else {
35            buf.append(())?;
36            Ok(IsNull::Yes)
37        }
38    }
39
40    fn size_hint(&self) -> usize {
41        // 1 sign + 15 digits + 1 dot
42        // See <https://docs.exasol.com/db/latest/sql_references/data_types/datatypedetails.htm#top>
43        17
44    }
45}
46
47impl Decode<'_, Exasol> for f64 {
48    fn decode(value: ExaValueRef<'_>) -> Result<Self, BoxDynError> {
49        match value.value {
50            Value::Number(n) => <Self as Deserialize>::deserialize(n).map_err(From::from),
51            Value::String(s) => serde_json::from_str(s).map_err(From::from),
52            v => Err(format!("invalid f64 value: {v}").into()),
53        }
54    }
55}