sqlx_scylladb_core/
value.rs

1use std::{borrow::Cow, sync::LazyLock};
2
3use bytes::Bytes;
4use scylla::{
5    cluster::metadata::ColumnType,
6    deserialize::{FrameSlice, value::DeserializeValue},
7};
8use sqlx::{Value, ValueRef};
9use sqlx_core::ext::ustr::UStr;
10
11use crate::{ScyllaDB, ScyllaDBError, ScyllaDBTypeInfo};
12
13/// Implementation of [sqlx::Value] for ScyllaDB.
14#[derive(Debug, Clone)]
15pub struct ScyllaDBValue {
16    column_name: UStr,
17    raw_value: Bytes,
18    column_type: ColumnType<'static>,
19    type_info: ScyllaDBTypeInfo,
20}
21
22impl Value for ScyllaDBValue {
23    type Database = ScyllaDB;
24
25    fn as_ref(&self) -> ScyllaDBValueRef<'_> {
26        ScyllaDBValueRef {
27            column_name: self.column_name.clone(),
28            raw_value: &self.raw_value,
29            column_type: &self.column_type,
30            type_info: self.type_info.clone(),
31        }
32    }
33
34    fn type_info(&self) -> Cow<'_, ScyllaDBTypeInfo> {
35        Cow::Borrowed(&self.type_info)
36    }
37
38    fn is_null(&self) -> bool {
39        self.type_info == ScyllaDBTypeInfo::Null
40    }
41}
42
43/// Implementation of [sqlx::ValueRef] for ScyllaDB.
44#[derive(Debug, Clone)]
45pub struct ScyllaDBValueRef<'r> {
46    column_name: UStr,
47    raw_value: &'r Bytes,
48    column_type: &'r ColumnType<'r>,
49    type_info: ScyllaDBTypeInfo,
50}
51
52impl<'r> ScyllaDBValueRef<'r> {
53    #[inline(always)]
54    pub(crate) fn new(
55        column_name: UStr,
56        type_info: ScyllaDBTypeInfo,
57        raw_value: &'r Bytes,
58        column_type: &'r ColumnType<'r>,
59    ) -> ScyllaDBValueRef<'r> {
60        Self {
61            column_name,
62            raw_value,
63            column_type,
64            type_info,
65        }
66    }
67
68    #[inline(always)]
69    pub(crate) fn null(column_name: UStr, column_type: &'r ColumnType<'r>) -> Self {
70        static EMPTY: LazyLock<Bytes> = LazyLock::new(|| Bytes::new());
71        Self {
72            column_name,
73            raw_value: &EMPTY,
74            column_type,
75            type_info: ScyllaDBTypeInfo::Null,
76        }
77    }
78
79    /// Return the column name.
80    #[inline(always)]
81    pub fn column_name(&self) -> UStr {
82        self.column_name.clone()
83    }
84
85    /// Return the scylladb column type.
86    #[inline(always)]
87    pub fn column_type(&self) -> ColumnType<'static> {
88        self.column_type.clone().into_owned()
89    }
90
91    /// Deserialize the response data from scylladb.
92    #[inline(always)]
93    pub fn deserialize<T>(&self) -> Result<T, ScyllaDBError>
94    where
95        T: DeserializeValue<'r, 'r>,
96    {
97        let frame_slice = FrameSlice::new(self.raw_value);
98        let val = <_ as DeserializeValue>::deserialize(self.column_type, Some(frame_slice))?;
99        Ok(val)
100    }
101}
102
103impl<'r> ValueRef<'r> for ScyllaDBValueRef<'r> {
104    type Database = ScyllaDB;
105
106    fn to_owned(&self) -> ScyllaDBValue {
107        ScyllaDBValue {
108            column_name: self.column_name.clone(),
109            column_type: self.column_type.clone().into_owned(),
110            raw_value: self.raw_value.clone(),
111            type_info: self.type_info.clone(),
112        }
113    }
114
115    fn type_info(&self) -> Cow<'_, ScyllaDBTypeInfo> {
116        Cow::Borrowed(&self.type_info)
117    }
118
119    fn is_null(&self) -> bool {
120        self.type_info == ScyllaDBTypeInfo::Null
121    }
122}