discord_cassandra_cpp/cassandra/
prepared.rs

1use crate::cassandra::error::*;
2use crate::cassandra::statement::Statement;
3use crate::cassandra::util::{Protected, ProtectedInner, ProtectedWithSession};
4use crate::{cassandra::data_type::ConstDataType, session_scope, Session};
5
6use crate::cassandra_sys::cass_prepared_bind;
7use crate::cassandra_sys::cass_prepared_free;
8use crate::cassandra_sys::cass_prepared_parameter_data_type;
9use crate::cassandra_sys::cass_prepared_parameter_data_type_by_name_n;
10use crate::cassandra_sys::cass_prepared_parameter_name;
11use crate::cassandra_sys::CassPrepared as _PreparedStatement;
12use std::os::raw::c_char;
13use std::{mem, slice, str};
14
15/// A statement that has been prepared against at least one Cassandra node.
16/// Instances of this class should not be created directly, but through Session.prepare().
17#[derive(Debug)]
18pub struct PreparedStatement<T = session_scope::Bound>(*const _PreparedStatement, Session<T>);
19
20unsafe impl<T: Send> Send for PreparedStatement<T> {}
21unsafe impl<T: Sync> Sync for PreparedStatement<T> {}
22
23impl<T> Drop for PreparedStatement<T> {
24    /// Frees a prepared statement
25    fn drop(&mut self) {
26        unsafe { cass_prepared_free(self.0) }
27    }
28}
29
30impl<T> ProtectedInner<*const _PreparedStatement> for PreparedStatement<T> {
31    #[inline(always)]
32    fn inner(&self) -> *const _PreparedStatement {
33        self.0
34    }
35}
36
37impl<T> ProtectedWithSession<*const _PreparedStatement, T> for PreparedStatement<T> {
38    #[inline(always)]
39    fn build(inner: *const _PreparedStatement, session: Session<T>) -> Self {
40        if inner.is_null() {
41            panic!("Unexpected null pointer")
42        };
43        PreparedStatement(inner, session)
44    }
45
46    #[inline(always)]
47    fn session(&self) -> &Session<T> {
48        &self.1
49    }
50}
51
52impl<T: Clone> PreparedStatement<T> {
53    /// Creates a bound statement from a pre-prepared statement.
54    pub fn bind(&self) -> Statement<T> {
55        unsafe { Statement::build(cass_prepared_bind(self.inner()), self.session().clone()) }
56    }
57
58    /// Returns the session of which this prepared statement is bound to.
59    pub fn session(&self) -> &Session<T> {
60        ProtectedWithSession::session(self)
61    }
62
63    /// Gets the name of a parameter at the specified index.
64    pub fn parameter_name(&self, index: usize) -> Result<&str> {
65        unsafe {
66            let mut name = mem::zeroed();
67            let mut name_length = mem::zeroed();
68            cass_prepared_parameter_name(self.0, index, &mut name, &mut name_length)
69                .to_result(())
70                .and_then(|_| {
71                    Ok(str::from_utf8(slice::from_raw_parts(
72                        name as *const u8,
73                        name_length as usize,
74                    ))?)
75                })
76        }
77    }
78
79    /// Gets the data type of a parameter at the specified index.
80    ///
81    /// Returns a reference to the data type of the parameter. Do not free
82    /// this reference as it is bound to the lifetime of the prepared.
83    pub fn parameter_data_type(&self, index: usize) -> Option<ConstDataType> {
84        unsafe {
85            let inner = cass_prepared_parameter_data_type(self.0, index);
86            if inner.is_null() {
87                None
88            } else {
89                Some(ConstDataType::build(inner))
90            }
91        }
92    }
93
94    /// Gets the data type of a parameter for the specified name.
95    ///
96    /// Returns a reference to the data type of the parameter. Do not free
97    /// this reference as it is bound to the lifetime of the prepared.
98    pub fn parameter_data_type_by_name(&self, name: &str) -> Option<ConstDataType> {
99        unsafe {
100            let name_ptr = name.as_ptr() as *const c_char;
101            let inner = cass_prepared_parameter_data_type_by_name_n(self.0, name_ptr, name.len());
102            if inner.is_null() {
103                None
104            } else {
105                Some(ConstDataType::build(inner))
106            }
107        }
108    }
109}