sqlx_exasol_impl/types/
hashtype.rs

1use serde::Deserialize;
2use sqlx_core::{
3    decode::Decode,
4    encode::{Encode, IsNull},
5    error::BoxDynError,
6    types::Type,
7};
8
9use crate::{
10    arguments::ExaBuffer,
11    database::Exasol,
12    type_info::{ExaDataType, ExaTypeInfo},
13    types::ExaHasArrayType,
14    value::ExaValueRef,
15};
16
17/// Newtype used for more explicit encoding/decoding of arbitrary length data into/from HASHTYPE
18/// columns.
19///
20/// Unlike UUID, this type is not subject to length checks because Exasol can accept multiple
21/// formats for these columns. While connections set the `HASHTYPE_FORMAT` database parameter to
22/// `HEX` when they're opened to allow the driver to reliably use the reported column size for
23/// length checks for UUIDs, this only affects the column output. Exasol will still accept any valid
24/// input for the column, which can have different lengths depending on the data format.
25///
26/// See <https://docs.exasol.com/db/latest/sql_references/data_types/datatypedetails.htm#HASHTYPE>, in particular for your exact database version.
27#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
28pub struct HashType(pub String);
29
30impl Type<Exasol> for HashType {
31    fn type_info() -> ExaTypeInfo {
32        ExaDataType::HashType { size: None }.into()
33    }
34}
35
36impl ExaHasArrayType for HashType {}
37
38impl Encode<'_, Exasol> for HashType {
39    fn encode_by_ref(&self, buf: &mut ExaBuffer) -> Result<IsNull, BoxDynError> {
40        <&str as Encode<Exasol>>::encode_by_ref(&self.0.as_str(), buf)
41    }
42
43    fn size_hint(&self) -> usize {
44        <&str as Encode<Exasol>>::size_hint(&self.0.as_str())
45    }
46}
47
48impl<'r> Decode<'r, Exasol> for HashType {
49    fn decode(value: ExaValueRef<'r>) -> Result<Self, BoxDynError> {
50        String::deserialize(value.value)
51            .map(HashType)
52            .map_err(From::from)
53    }
54}