1use crate::ast::expr::Expr;
7use crate::catalog::persistent::{DataSourceFormat, TableType};
8use crate::planner::types::ResolvedType;
9use std::collections::HashMap;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub enum StorageType {
14 Row,
16 Columnar,
18}
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub enum RowIdMode {
23 None,
25 Direct,
27}
28
29#[derive(Debug, Clone, Copy, PartialEq, Eq)]
31pub enum Compression {
32 None,
33 Lz4,
34 Zstd,
35}
36
37#[derive(Debug, Clone, PartialEq, Eq)]
39pub struct StorageOptions {
40 pub storage_type: StorageType,
41 pub compression: Compression,
42 pub row_group_size: u32,
43 pub row_id_mode: RowIdMode,
44}
45
46impl Default for StorageOptions {
47 fn default() -> Self {
48 Self {
49 storage_type: StorageType::Row,
50 compression: Compression::Lz4,
51 row_group_size: 100_000,
52 row_id_mode: RowIdMode::Direct,
53 }
54 }
55}
56
57#[derive(Debug, Clone)]
83pub struct TableMetadata {
84 pub table_id: u32,
86 pub name: String,
88 pub catalog_name: String,
90 pub namespace_name: String,
92 pub table_type: TableType,
94 pub data_source_format: DataSourceFormat,
96 pub columns: Vec<ColumnMetadata>,
98 pub primary_key: Option<Vec<String>>,
100 pub storage_options: StorageOptions,
102 pub storage_location: Option<String>,
104 pub comment: Option<String>,
106 pub properties: HashMap<String, String>,
108}
109
110impl TableMetadata {
111 pub fn new(name: impl Into<String>, columns: Vec<ColumnMetadata>) -> Self {
116 Self {
117 table_id: 0,
118 name: name.into(),
119 catalog_name: "default".to_string(),
120 namespace_name: "default".to_string(),
121 table_type: TableType::Managed,
122 data_source_format: DataSourceFormat::default(),
123 columns,
124 primary_key: None,
125 storage_options: StorageOptions::default(),
126 storage_location: None,
127 comment: None,
128 properties: HashMap::new(),
129 }
130 }
131
132 pub fn with_table_id(mut self, table_id: u32) -> Self {
134 self.table_id = table_id;
135 self
136 }
137
138 pub fn with_primary_key(mut self, columns: Vec<String>) -> Self {
140 self.primary_key = Some(columns);
141 self
142 }
143
144 pub fn get_column(&self, name: &str) -> Option<&ColumnMetadata> {
163 self.columns.iter().find(|c| c.name == name)
164 }
165
166 pub fn get_column_index(&self, name: &str) -> Option<usize> {
170 self.columns.iter().position(|c| c.name == name)
171 }
172
173 pub fn column_names(&self) -> Vec<&str> {
190 self.columns.iter().map(|c| c.name.as_str()).collect()
191 }
192
193 pub fn column_count(&self) -> usize {
195 self.columns.len()
196 }
197}
198
199#[derive(Debug, Clone)]
219pub struct ColumnMetadata {
220 pub name: String,
222 pub data_type: ResolvedType,
224 pub not_null: bool,
226 pub primary_key: bool,
228 pub unique: bool,
230 pub default: Option<Expr>,
232}
233
234impl ColumnMetadata {
235 pub fn new(name: impl Into<String>, data_type: ResolvedType) -> Self {
239 Self {
240 name: name.into(),
241 data_type,
242 not_null: false,
243 primary_key: false,
244 unique: false,
245 default: None,
246 }
247 }
248
249 pub fn with_not_null(mut self, not_null: bool) -> Self {
251 self.not_null = not_null;
252 self
253 }
254
255 pub fn with_primary_key(mut self, primary_key: bool) -> Self {
257 self.primary_key = primary_key;
258 self
259 }
260
261 pub fn with_unique(mut self, unique: bool) -> Self {
263 self.unique = unique;
264 self
265 }
266
267 pub fn with_default(mut self, default: Expr) -> Self {
269 self.default = Some(default);
270 self
271 }
272}
273
274#[cfg(test)]
275mod tests {
276 use super::*;
277
278 #[test]
279 fn test_table_metadata_new() {
280 let table = TableMetadata::new("users", vec![]);
281 assert_eq!(table.table_id, 0);
282 assert_eq!(table.name, "users");
283 assert!(table.columns.is_empty());
284 assert!(table.primary_key.is_none());
285 }
286
287 #[test]
288 fn test_table_metadata_with_table_id() {
289 let table = TableMetadata::new("users", vec![]).with_table_id(42);
290 assert_eq!(table.table_id, 42);
291 assert_eq!(table.name, "users");
292 }
293
294 #[test]
295 fn test_table_metadata_with_columns() {
296 let columns = vec![
297 ColumnMetadata::new("id", ResolvedType::Integer),
298 ColumnMetadata::new("name", ResolvedType::Text),
299 ];
300 let table = TableMetadata::new("users", columns);
301
302 assert_eq!(table.columns.len(), 2);
303 assert_eq!(table.columns[0].name, "id");
304 assert_eq!(table.columns[1].name, "name");
305 }
306
307 #[test]
308 fn test_table_metadata_with_primary_key() {
309 let table = TableMetadata::new("users", vec![])
310 .with_primary_key(vec!["id".to_string(), "tenant_id".to_string()]);
311
312 assert_eq!(
313 table.primary_key,
314 Some(vec!["id".to_string(), "tenant_id".to_string()])
315 );
316 }
317
318 #[test]
319 fn test_get_column() {
320 let columns = vec![
321 ColumnMetadata::new("id", ResolvedType::Integer),
322 ColumnMetadata::new("name", ResolvedType::Text),
323 ];
324 let table = TableMetadata::new("users", columns);
325
326 let id_col = table.get_column("id");
327 assert!(id_col.is_some());
328 assert_eq!(id_col.unwrap().name, "id");
329 assert_eq!(id_col.unwrap().data_type, ResolvedType::Integer);
330
331 let name_col = table.get_column("name");
332 assert!(name_col.is_some());
333 assert_eq!(name_col.unwrap().data_type, ResolvedType::Text);
334
335 assert!(table.get_column("unknown").is_none());
336 }
337
338 #[test]
339 fn test_get_column_index() {
340 let columns = vec![
341 ColumnMetadata::new("id", ResolvedType::Integer),
342 ColumnMetadata::new("name", ResolvedType::Text),
343 ColumnMetadata::new("age", ResolvedType::Integer),
344 ];
345 let table = TableMetadata::new("users", columns);
346
347 assert_eq!(table.get_column_index("id"), Some(0));
348 assert_eq!(table.get_column_index("name"), Some(1));
349 assert_eq!(table.get_column_index("age"), Some(2));
350 assert_eq!(table.get_column_index("unknown"), None);
351 }
352
353 #[test]
354 fn test_column_names() {
355 let columns = vec![
356 ColumnMetadata::new("id", ResolvedType::Integer),
357 ColumnMetadata::new("name", ResolvedType::Text),
358 ColumnMetadata::new("age", ResolvedType::Integer),
359 ];
360 let table = TableMetadata::new("users", columns);
361
362 assert_eq!(table.column_names(), vec!["id", "name", "age"]);
363 }
364
365 #[test]
366 fn test_column_count() {
367 let table = TableMetadata::new(
368 "users",
369 vec![
370 ColumnMetadata::new("id", ResolvedType::Integer),
371 ColumnMetadata::new("name", ResolvedType::Text),
372 ],
373 );
374 assert_eq!(table.column_count(), 2);
375 }
376
377 #[test]
378 fn test_column_metadata_new() {
379 let column = ColumnMetadata::new("id", ResolvedType::Integer);
380
381 assert_eq!(column.name, "id");
382 assert_eq!(column.data_type, ResolvedType::Integer);
383 assert!(!column.not_null);
384 assert!(!column.primary_key);
385 assert!(!column.unique);
386 assert!(column.default.is_none());
387 }
388
389 #[test]
390 fn test_column_metadata_constraints() {
391 let column = ColumnMetadata::new("id", ResolvedType::Integer)
392 .with_not_null(true)
393 .with_primary_key(true)
394 .with_unique(true);
395
396 assert!(column.not_null);
397 assert!(column.primary_key);
398 assert!(column.unique);
399 }
400
401 #[test]
402 fn test_storage_options_default() {
403 let options = StorageOptions::default();
404 assert_eq!(options.storage_type, StorageType::Row);
405 assert_eq!(options.compression, Compression::Lz4);
406 assert_eq!(options.row_group_size, 100_000);
407 assert_eq!(options.row_id_mode, RowIdMode::Direct);
408 }
409
410 #[test]
411 fn test_table_metadata_sets_default_storage_options() {
412 let table = TableMetadata::new("users", vec![]);
413 assert_eq!(table.storage_options, StorageOptions::default());
414 }
415}