1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
use std::fmt;
use rmpv::Value;
use serde::Deserialize;
use super::{IndexMetadata, SystemSpacesId};
use crate::{client::ConnectionLike, utils::UniqueIdNameMap, Error};
/// Space metadata from with its indices metadata from [system views](https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_space/system_views/).
#[derive(Clone, Deserialize)]
pub struct SpaceMetadata {
id: u32,
owner_id: u32,
name: String,
_engine: String, // TODO: enum
_fields_count: u32,
_flags: Value, // TODO: parse flags
_format: Vec<Value>, // TODO: parse format or remove it entirely
// TODO: maybe implement hash directly on IndexMetadata and store in set
// TODO: maybe vec or btreemap would be faster
#[serde(skip)]
indices: UniqueIdNameMap<IndexMetadata>,
}
impl fmt::Debug for SpaceMetadata {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SpaceMetadata")
.field("id", &self.id)
.field("owner_id", &self.owner_id)
.field("name", &self.name)
.field("engine", &self._engine)
// TODO: uncomment when fields implemented
// .field("_flags", &self._flags)
// .field("_format", &self._format)
.field("indices", &self.indices)
.finish()
}
}
impl SpaceMetadata {
/// Load metadata of single space by its id.
pub async fn load_by_id(conn: impl ConnectionLike, id: u32) -> Result<Option<Self>, Error> {
// 0 - primary id index
Self::load(conn, 0, id).await
}
/// Load metadata of single space by its name.
pub async fn load_by_name(
conn: impl ConnectionLike,
name: &str,
) -> Result<Option<Self>, Error> {
// 2 - index on 'name' field
Self::load(conn, 2, name).await
}
/// Load metadata of single space by key.
async fn load(
conn: impl ConnectionLike,
index_id: u32,
key: impl Into<Value>,
) -> Result<Option<Self>, Error> {
let Some(mut this): Option<Self> = conn
.select(
SystemSpacesId::VSpace as u32,
index_id,
None,
None,
None,
vec![key.into()],
)
.await?
.into_iter()
.next() else {
return Ok(None)
};
this.load_indices(conn).await?;
Ok(Some(this))
}
/// Load indices metadata into current space metadata.
async fn load_indices(&mut self, conn: impl ConnectionLike) -> Result<(), Error> {
self.indices = IndexMetadata::load_by_space_id(conn, self.id)
.await
.and_then(|x| {
UniqueIdNameMap::try_from_iter(x).map_err(|err| {
Error::MetadataLoad(err.context("Failed to load indices metadata"))
})
})?;
Ok(())
}
/// Returns the id of this space.
pub fn id(&self) -> u32 {
self.id
}
/// Returns user id of ther owner of this space.
pub fn owner_id(&self) -> u32 {
self.owner_id
}
/// Returns a name of this space.
pub fn name(&self) -> &str {
self.name.as_ref()
}
/// Returns map of idices in this space.
pub fn indices(&self) -> &UniqueIdNameMap<IndexMetadata> {
&self.indices
}
}