sqlx_exasol_impl/types/
int.rs

1use std::ops::Range;
2
3use serde::Deserialize;
4use serde_json::Value;
5use sqlx_core::{
6    decode::Decode,
7    encode::{Encode, IsNull},
8    error::BoxDynError,
9    types::Type,
10};
11
12use crate::{
13    arguments::ExaBuffer,
14    database::Exasol,
15    type_info::{Decimal, ExaDataType, ExaTypeInfo},
16    types::ExaHasArrayType,
17    value::ExaValueRef,
18};
19
20/// Numbers within this range must be serialized/deserialized as integers.
21/// The ones above/under these thresholds are treated as strings.
22const NUMERIC_I64_RANGE: Range<i64> = -999_999_999_999_999_999..1_000_000_000_000_000_000;
23
24impl Type<Exasol> for i8 {
25    fn type_info() -> ExaTypeInfo {
26        ExaDataType::Decimal(Decimal {
27            precision: Some(Decimal::MAX_8BIT_PRECISION),
28            scale: 0,
29        })
30        .into()
31    }
32}
33
34impl Type<Exasol> for i16 {
35    fn type_info() -> ExaTypeInfo {
36        ExaDataType::Decimal(Decimal {
37            precision: Some(Decimal::MAX_16BIT_PRECISION),
38            scale: 0,
39        })
40        .into()
41    }
42}
43
44impl Type<Exasol> for i32 {
45    fn type_info() -> ExaTypeInfo {
46        ExaDataType::Decimal(Decimal {
47            precision: Some(Decimal::MAX_32BIT_PRECISION),
48            scale: 0,
49        })
50        .into()
51    }
52}
53
54impl Type<Exasol> for i64 {
55    fn type_info() -> ExaTypeInfo {
56        ExaDataType::Decimal(Decimal {
57            precision: Some(Decimal::MAX_64BIT_PRECISION),
58            scale: 0,
59        })
60        .into()
61    }
62}
63
64impl ExaHasArrayType for i8 {}
65impl ExaHasArrayType for i16 {}
66impl ExaHasArrayType for i32 {}
67impl ExaHasArrayType for i64 {}
68
69impl Encode<'_, Exasol> for i8 {
70    fn encode_by_ref(&self, buf: &mut ExaBuffer) -> Result<IsNull, BoxDynError> {
71        buf.append(self)?;
72        Ok(IsNull::No)
73    }
74
75    fn size_hint(&self) -> usize {
76        // sign + max num digits
77        1 + Decimal::MAX_8BIT_PRECISION as usize
78    }
79}
80
81impl Encode<'_, Exasol> for i16 {
82    fn encode_by_ref(&self, buf: &mut ExaBuffer) -> Result<IsNull, BoxDynError> {
83        buf.append(self)?;
84        Ok(IsNull::No)
85    }
86
87    fn size_hint(&self) -> usize {
88        // sign + max num digits
89        1 + Decimal::MAX_16BIT_PRECISION as usize
90    }
91}
92
93impl Encode<'_, Exasol> for i32 {
94    fn encode_by_ref(&self, buf: &mut ExaBuffer) -> Result<IsNull, BoxDynError> {
95        buf.append(self)?;
96        Ok(IsNull::No)
97    }
98
99    fn size_hint(&self) -> usize {
100        // sign + max num digits
101        1 + Decimal::MAX_32BIT_PRECISION as usize
102    }
103}
104
105impl Encode<'_, Exasol> for i64 {
106    fn encode_by_ref(&self, buf: &mut ExaBuffer) -> Result<IsNull, BoxDynError> {
107        if NUMERIC_I64_RANGE.contains(self) {
108            buf.append(self)?;
109        } else {
110            // Large numbers get serialized as strings
111            buf.append(format_args!("{self}"))?;
112        }
113
114        Ok(IsNull::No)
115    }
116
117    fn size_hint(&self) -> usize {
118        // 1 quote + 1 sign + max num digits + 1 quote
119        2 + Decimal::MAX_64BIT_PRECISION as usize + 1
120    }
121}
122
123impl Decode<'_, Exasol> for i8 {
124    fn decode(value: ExaValueRef<'_>) -> Result<Self, BoxDynError> {
125        <Self as Deserialize>::deserialize(value.value).map_err(From::from)
126    }
127}
128
129impl Decode<'_, Exasol> for i16 {
130    fn decode(value: ExaValueRef<'_>) -> Result<Self, BoxDynError> {
131        <Self as Deserialize>::deserialize(value.value).map_err(From::from)
132    }
133}
134
135impl Decode<'_, Exasol> for i32 {
136    fn decode(value: ExaValueRef<'_>) -> Result<Self, BoxDynError> {
137        <Self as Deserialize>::deserialize(value.value).map_err(From::from)
138    }
139}
140
141impl Decode<'_, Exasol> for i64 {
142    fn decode(value: ExaValueRef<'_>) -> Result<Self, BoxDynError> {
143        match value.value {
144            Value::Number(n) => <Self as Deserialize>::deserialize(n).map_err(From::from),
145            Value::String(s) => serde_json::from_str(s).map_err(From::from),
146            v => Err(format!("invalid i64 value: {v}").into()),
147        }
148    }
149}