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    pub(crate) fn is_null(&self) -> bool {
80        self.type_info == ScyllaDBTypeInfo::Null
81    }
82
83    /// Return the column name.
84    #[inline(always)]
85    pub fn column_name(&self) -> UStr {
86        self.column_name.clone()
87    }
88
89    /// Return the scylladb column type.
90    #[inline(always)]
91    pub fn column_type(&self) -> ColumnType<'static> {
92        self.column_type.clone().into_owned()
93    }
94
95    /// Deserialize the response data from scylladb.
96    #[inline(always)]
97    pub fn deserialize<T>(&self) -> Result<T, ScyllaDBError>
98    where
99        T: DeserializeValue<'r, 'r>,
100    {
101        let val = if !self.is_null() {
102            let frame_slice = FrameSlice::new(self.raw_value);
103            <_ as DeserializeValue>::deserialize(self.column_type, Some(frame_slice))?
104        } else {
105            <_ as DeserializeValue>::deserialize(self.column_type, None)?
106        };
107
108        Ok(val)
109    }
110}
111
112impl<'r> ValueRef<'r> for ScyllaDBValueRef<'r> {
113    type Database = ScyllaDB;
114
115    fn to_owned(&self) -> ScyllaDBValue {
116        ScyllaDBValue {
117            column_name: self.column_name.clone(),
118            column_type: self.column_type.clone().into_owned(),
119            raw_value: self.raw_value.clone(),
120            type_info: self.type_info.clone(),
121        }
122    }
123
124    fn type_info(&self) -> Cow<'_, ScyllaDBTypeInfo> {
125        Cow::Borrowed(&self.type_info)
126    }
127
128    fn is_null(&self) -> bool {
129        self.type_info == ScyllaDBTypeInfo::Null
130    }
131}