tarantool_rs/client/schema/
space.rs1use std::{
2 fmt::{self, Debug},
3 sync::Arc,
4};
5
6use anyhow::Context;
7use rmpv::Value;
8use serde::{de::DeserializeOwned, Deserialize};
9
10use super::{Index, IndexMetadata, OwnedIndex, SchemaEntityKey, SystemSpacesId, PRIMARY_INDEX_ID};
11use crate::{
12 client::ExecutorExt, tuple::Tuple, utils::UniqueIdNameMap, DmoResponse, Error, Executor,
13 IteratorType, Result, Transaction,
14};
15
16#[derive(Clone, Deserialize)]
18pub struct SpaceMetadata {
19 pub(super) id: u32,
20 owner_id: u32,
21 name: String,
22 _engine: String, _fields_count: u32,
24 _flags: Value, _format: Vec<Value>, }
27
28impl fmt::Debug for SpaceMetadata {
29 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30 f.debug_struct("SpaceMetadata")
31 .field("id", &self.id)
32 .field("owner_id", &self.owner_id)
33 .field("name", &self.name)
34 .field("engine", &self._engine)
35 .finish()
39 }
40}
41
42impl SpaceMetadata {
43 async fn load(conn: impl ExecutorExt, key: SchemaEntityKey) -> Result<Option<Self>> {
47 Ok(conn
48 .select(
49 SystemSpacesId::VSpace as u32,
50 key.space_index_id(),
51 None,
52 None,
53 None,
54 (key.into_value(),),
55 )
56 .await?
57 .into_iter()
58 .next())
59 }
60
61 pub fn id(&self) -> u32 {
63 self.id
64 }
65
66 pub fn owner_id(&self) -> u32 {
68 self.owner_id
69 }
70
71 pub fn name(&self) -> &str {
73 self.name.as_ref()
74 }
75
76 }
81
82pub struct Space<E> {
87 executor: E,
88 metadata: Arc<SpaceMetadata>,
89 primary_index_metadata: Arc<IndexMetadata>,
90 indices_metadata: Arc<UniqueIdNameMap<IndexMetadata>>,
91}
92
93impl<E: Clone> Clone for Space<E> {
94 fn clone(&self) -> Self {
95 Self {
96 executor: self.executor.clone(),
97 metadata: self.metadata.clone(),
98 primary_index_metadata: self.primary_index_metadata.clone(),
99 indices_metadata: self.indices_metadata.clone(),
100 }
101 }
102}
103
104impl<E> Space<E> {
105 fn get_index(&self, key: impl Into<SchemaEntityKey>) -> Option<&Arc<IndexMetadata>> {
106 match key.into() {
107 SchemaEntityKey::Id(x) => self.indices_metadata.get_by_id(x),
108 SchemaEntityKey::Name(x) => self.indices_metadata.get_by_name(&x),
109 }
110 }
111
112 pub fn executor(&self) -> &E {
113 &self.executor
114 }
115
116 pub fn metadata(&self) -> &SpaceMetadata {
117 &self.metadata
118 }
119
120 pub fn into_executor(self) -> E {
121 self.executor
122 }
123
124 pub fn primary_index(&self) -> Index<&E> {
125 Index::new(&self.executor, &self.primary_index_metadata, &self.metadata)
126 }
127
128 pub fn index(&self, key: impl Into<SchemaEntityKey>) -> Option<Index<&E>> {
129 self.get_index(key)
130 .map(|index| Index::new(&self.executor, index, &self.metadata))
131 }
132}
133
134impl<E: Clone> Space<E> {
135 pub fn owned_primary_index(&self) -> OwnedIndex<E> {
136 OwnedIndex::new(
137 self.executor.clone(),
138 self.primary_index_metadata.clone(),
139 self.metadata.clone(),
140 )
141 }
142
143 pub fn owned_index(&self, key: impl Into<SchemaEntityKey>) -> Option<OwnedIndex<E>> {
144 self.get_index(key).map(|index| {
145 OwnedIndex::new(self.executor.clone(), index.clone(), self.metadata.clone())
146 })
147 }
148}
149
150impl<E: Executor> Space<E> {
151 pub(crate) async fn load(executor: E, key: SchemaEntityKey) -> Result<Option<Self>> {
155 let Some(space_metadata) = SpaceMetadata::load(&executor, key).await? else {
156 return Ok(None);
157 };
158
159 let indices = IndexMetadata::load_by_space_id(&executor, space_metadata.id)
160 .await
161 .and_then(|x| {
162 UniqueIdNameMap::try_from_iter(x)
163 .context("Duplicate indices in space")
164 .map_err(Error::Other)
165 })?;
166 let Some(primary_index) = indices.get_by_id(PRIMARY_INDEX_ID).cloned() else {
167 return Err(Error::SpaceMissingPrimaryIndex);
168 };
169
170 Ok(Some(Self {
171 executor,
172 metadata: space_metadata.into(),
173 primary_index_metadata: primary_index,
174 indices_metadata: indices.into(),
175 }))
176 }
177
178 pub fn indices(&self) -> impl Iterator<Item = Index<&E>> {
180 self.indices_metadata
181 .iter()
182 .map(|index| Index::new(&self.executor, index, &self.metadata))
183 }
184
185 pub async fn select<T, A>(
189 &self,
190 limit: Option<u32>,
191 offset: Option<u32>,
192 iterator: Option<IteratorType>,
193 keys: A,
194 ) -> Result<Vec<T>>
195 where
196 T: DeserializeOwned,
197 A: Tuple + Send,
198 {
199 self.executor
200 .select(
201 self.metadata.id,
202 PRIMARY_INDEX_ID,
203 limit,
204 offset,
205 iterator,
206 keys,
207 )
208 .await
209 }
210
211 pub async fn insert<T>(&self, tuple: T) -> Result<DmoResponse>
215 where
216 T: Tuple + Send,
217 {
218 self.executor.insert(self.metadata.id, tuple).await
219 }
220
221 pub async fn update<K, O>(&self, keys: K, ops: O) -> Result<DmoResponse>
225 where
226 K: Tuple + Send,
227 O: Tuple + Send,
228 {
229 self.executor
230 .update(self.metadata.id, PRIMARY_INDEX_ID, keys, ops)
231 .await
232 }
233
234 pub async fn upsert<T, O>(&self, tuple: T, ops: O) -> Result<DmoResponse>
238 where
239 T: Tuple + Send,
240 O: Tuple + Send,
241 {
242 self.executor.upsert(self.metadata.id, tuple, ops).await
243 }
244
245 pub async fn replace<T>(&self, tuple: T) -> Result<DmoResponse>
249 where
250 T: Tuple + Send,
251 {
252 self.executor.replace(self.metadata.id, tuple).await
253 }
254
255 pub async fn delete<T>(&self, keys: T) -> Result<DmoResponse>
259 where
260 T: Tuple + Send,
261 {
262 self.executor
263 .delete(self.metadata.id, PRIMARY_INDEX_ID, keys)
264 .await
265 }
266}
267
268impl Space<Transaction> {
269 pub async fn commit(self) -> Result<()> {
271 self.executor.commit().await
272 }
273
274 pub async fn rollback(self) -> Result<()> {
276 self.executor.rollback().await
277 }
278}
279
280impl<E: Debug> fmt::Debug for Space<E> {
281 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
282 f.debug_struct("SpaceMetadata")
283 .field("executor", &self.executor)
284 .field("metadata", &self.metadata)
285 .finish()
286 }
287}