kassandra/cql/schema/
mod.rs

1pub mod column;
2pub mod keyspace;
3pub mod persisted;
4pub mod system;
5pub mod table;
6
7use std::collections::{btree_map::Entry, BTreeMap};
8
9use derive_more::{Deref, DerefMut};
10use serde::{Deserialize, Serialize};
11
12pub use self::{
13    column::{Column, ColumnKind, ColumnType},
14    persisted::PersistedSchema,
15    table::{PrimaryKey, PrimaryKeyColumn, Table, TableSchema},
16};
17use crate::{
18    cql::{
19        literal::Literal,
20        schema::{
21            keyspace::{Keyspace, Strategy},
22            system::{system_keyspace, system_schema_keyspace},
23        },
24    },
25    error::DbError,
26    frame::response::event::SchemaChangeEvent,
27};
28
29pub trait Catalog {
30    fn create_keyspace(
31        &mut self,
32        keyspace: String,
33        ignore_existence: bool,
34        replication: Strategy,
35    ) -> Result<&Keyspace, DbError>;
36
37    fn create_table(
38        &mut self,
39        keyspace: String,
40        table: String,
41        ignore_existence: bool,
42        schema: TableSchema,
43        options: Vec<(String, Literal)>,
44    ) -> Result<&Table, DbError>;
45
46    fn create_type(
47        &mut self,
48        keyspace: Option<String>,
49        table: String,
50        columns: Vec<(String, String)>,
51    ) -> Result<SchemaChangeEvent, DbError>;
52
53    fn get_table(&self, keyspace: &str, table: &str) -> Option<&TableSchema>;
54}
55
56#[derive(Debug, Clone, Serialize, Deserialize, Deref, DerefMut)]
57#[serde(transparent)]
58pub struct Schema(pub BTreeMap<String, Keyspace>);
59
60impl Default for Schema {
61    fn default() -> Self {
62        Self(
63            [system_keyspace(), system_schema_keyspace()]
64                .into_iter()
65                .collect(),
66        )
67    }
68}
69
70impl Catalog for Schema {
71    fn create_keyspace(
72        &mut self,
73        keyspace: String,
74        ignore_existence: bool,
75        strategy: Strategy,
76    ) -> Result<&Keyspace, DbError> {
77        match self.0.entry(keyspace) {
78            Entry::Occupied(occupied) if ignore_existence => Ok(&*occupied.into_mut()),
79            Entry::Occupied(occupied) => Err(DbError::AlreadyExists {
80                keyspace: occupied.key().clone(),
81                table: "".to_string(),
82            }),
83            Entry::Vacant(vacant) => {
84                let name = vacant.key().clone();
85                let ks = vacant.insert(Keyspace {
86                    name,
87                    strategy,
88                    tables: Default::default(),
89                    user_defined_types: Default::default(),
90                });
91
92                Ok(&*ks)
93            }
94        }
95    }
96
97    fn create_table(
98        &mut self,
99        keyspace: String,
100        table: String,
101        ignore_existence: bool,
102        schema: TableSchema,
103        _options: Vec<(String, Literal)>,
104    ) -> Result<&Table, DbError> {
105        let ks = self.0.get_mut(&keyspace).ok_or(DbError::Invalid)?;
106
107        match ks.tables.entry(table.clone()) {
108            Entry::Occupied(occupied) if ignore_existence => Ok(&*occupied.into_mut()),
109            Entry::Occupied(_) => Err(DbError::AlreadyExists { keyspace, table }),
110            Entry::Vacant(vacant) => {
111                let table = vacant.insert(Table {
112                    keyspace,
113                    name: table,
114                    schema,
115                });
116
117                Ok(&*table)
118            }
119        }
120    }
121
122    fn create_type(
123        &mut self,
124        _keyspace: Option<String>,
125        _table: String,
126        _columns: Vec<(String, String)>,
127    ) -> Result<SchemaChangeEvent, DbError> {
128        todo!()
129    }
130
131    fn get_table(&self, keyspace: &str, table: &str) -> Option<&TableSchema> {
132        self.0.get(keyspace)?.tables.get(table).map(|it| &it.schema)
133    }
134}
135
136impl<'a, C: Catalog> Catalog for &'a mut C {
137    fn create_keyspace(
138        &mut self,
139        keyspace: String,
140        ignore_existence: bool,
141        replication: Strategy,
142    ) -> Result<&Keyspace, DbError> {
143        (*self).create_keyspace(keyspace, ignore_existence, replication)
144    }
145
146    fn create_table(
147        &mut self,
148        keyspace: String,
149        table: String,
150        ignore_existence: bool,
151        schema: TableSchema,
152        options: Vec<(String, Literal)>,
153    ) -> Result<&Table, DbError> {
154        (*self).create_table(keyspace, table, ignore_existence, schema, options)
155    }
156
157    fn create_type(
158        &mut self,
159        _keyspace: Option<String>,
160        _table: String,
161        _columns: Vec<(String, String)>,
162    ) -> Result<SchemaChangeEvent, DbError> {
163        todo!()
164    }
165
166    fn get_table(&self, keyspace: &str, table: &str) -> Option<&TableSchema> {
167        (**self).get_table(keyspace, table)
168    }
169}