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}