discord_cassandra_cpp/cassandra/
session.rs1#![allow(non_camel_case_types)]
2#![allow(dead_code)]
3#![allow(missing_copy_implementations)]
4
5use crate::cassandra::cluster::Cluster;
6use crate::cassandra::error::*;
7use crate::cassandra::future::CassFuture;
8use crate::cassandra::metrics::SessionMetrics;
9use crate::cassandra::prepared::PreparedStatement;
10use crate::cassandra::result::CassResult;
11use crate::cassandra::schema::schema_meta::SchemaMeta;
12use crate::cassandra::statement::Statement;
13use crate::cassandra::util::{Protected, ProtectedInner};
14use crate::{cassandra::batch::Batch, BatchType};
15
16use crate::cassandra_sys::cass_session_close;
17use crate::cassandra_sys::cass_session_connect;
18use crate::cassandra_sys::cass_session_connect_keyspace_n;
19use crate::cassandra_sys::cass_session_execute;
20use crate::cassandra_sys::cass_session_execute_batch;
21use crate::cassandra_sys::cass_session_free;
22use crate::cassandra_sys::cass_session_get_metrics;
23use crate::cassandra_sys::cass_session_get_schema_meta;
24use crate::cassandra_sys::cass_session_new;
25use crate::cassandra_sys::cass_session_prepare_n;
26use crate::cassandra_sys::CassSession as _Session;
27
28use std::ffi::NulError;
29use std::mem;
30use std::os::raw::c_char;
31use std::sync::Arc;
32
33#[derive(Debug, Eq, PartialEq)]
34struct SessionInner<T>(T, *mut _Session);
35
36unsafe impl<T: Send> Send for SessionInner<T> {}
39unsafe impl<T: Sync> Sync for SessionInner<T> {}
40
41impl<T> SessionInner<T> {
42 fn new(bound: T, inner: *mut _Session) -> Arc<Self> {
43 Arc::new(Self(bound, inner))
44 }
45}
46
47pub trait SessionScope: session_scope::sealed::Sealed + Clone + Send + Sync + 'static {}
52
53pub mod session_scope {
55 pub use super::SessionScope;
56
57 pub(super) mod sealed {
58 pub trait Sealed {}
59 }
60
61 #[derive(Debug, Clone)]
63 pub struct Bound {
64 pub(crate) keyspace: String,
65 }
66
67 impl Bound {
68 pub(crate) fn new(keyspace: impl Into<String>) -> Self {
69 Self {
70 keyspace: keyspace.into(),
71 }
72 }
73 }
74
75 #[derive(Debug, Clone)]
77 pub struct Unbound;
78
79 impl sealed::Sealed for Bound {}
80 impl sealed::Sealed for Unbound {}
81
82 impl super::SessionScope for Bound {}
83 impl super::SessionScope for Unbound {}
84}
85#[derive(Debug, Clone)]
92pub struct Session<T = session_scope::Bound>(Arc<SessionInner<T>>);
93
94impl<T> Eq for Session<T> {}
95
96impl<T> PartialEq for Session<T> {
97 fn eq(&self, other: &Self) -> bool {
98 (self.0).1 == (other.0).1
99 }
100}
101
102unsafe impl<T: Send> Send for Session<T> {}
105unsafe impl<T: Sync> Sync for Session<T> {}
106
107impl<T> ProtectedInner<*mut _Session> for SessionInner<T> {
108 fn inner(&self) -> *mut _Session {
109 self.1
110 }
111}
112
113impl<T> ProtectedInner<*mut _Session> for Session<T> {
114 fn inner(&self) -> *mut _Session {
115 self.0.inner()
116 }
117}
118
119impl Protected<*mut _Session> for Session<session_scope::Unbound> {
120 fn build(inner: *mut _Session) -> Self {
121 if inner.is_null() {
122 panic!("Unexpected null pointer")
123 };
124 Session(SessionInner::new(session_scope::Unbound, inner))
125 }
126}
127
128impl<T> Drop for SessionInner<T> {
129 fn drop(&mut self) {
132 unsafe { cass_session_free(self.1) }
133 }
134}
135
136impl Default for Session<session_scope::Unbound> {
137 fn default() -> Session<session_scope::Unbound> {
138 Session::new(session_scope::Unbound)
139 }
140}
141
142impl<S> Session<S>
143where
144 S: SessionScope,
145{
146 pub(crate) fn new(bound: S) -> Self {
147 unsafe { Session(SessionInner::new(bound, cass_session_new())) }
148 }
149
150 pub fn statement(&self, query: impl AsRef<str>) -> Statement<S> {
152 let query = query.as_ref();
153 let param_count = query.matches("?").count();
154 Statement::new(self.clone(), query, param_count)
155 }
156
157 pub async fn execute(&self, query: impl AsRef<str>) -> Result<CassResult> {
159 let statement = self.statement(query);
160 statement.execute().await
161 }
162
163 pub fn batch(&self, batch_type: BatchType) -> Batch<S> {
165 Batch::new(batch_type, self.clone())
166 }
167
168 pub fn get_schema_meta(&self) -> SchemaMeta {
173 unsafe { SchemaMeta::build(cass_session_get_schema_meta(self.inner())) }
174 }
175
176 pub fn get_metrics(&self) -> SessionMetrics {
178 unsafe {
179 let mut metrics = mem::zeroed();
180 cass_session_get_metrics(self.inner(), &mut metrics);
181 SessionMetrics::build(&metrics)
182 }
183 }
184
185 pub async fn prepare(&self, query: impl AsRef<str>) -> Result<PreparedStatement<S>> {
187 let query = query.as_ref();
188 let prepare_future = {
189 let query_ptr = query.as_ptr() as *const c_char;
190 CassFuture::build(self.clone(), unsafe {
191 cass_session_prepare_n(self.inner(), query_ptr, query.len())
192 })
193 };
194 prepare_future.await
195 }
196
197 }
201
202impl Session<session_scope::Bound> {
203 pub fn keyspace(&self) -> &str {
205 &(self.0).0.keyspace
206 }
207}