Skip to main content

reddb_server/application/
ports_impls_schema.rs

1use super::*;
2use crate::application::schema::{CreateTablePartitionKind, CreateTablePartitionSpec};
3use reddb_rql::ast::{
4    CreateColumnDef, CreateTableQuery, CreateTimeSeriesQuery, DropTableQuery, DropTimeSeriesQuery,
5};
6use reddb_rql::ast::{PartitionKind, PartitionSpec};
7use reddb_types::SqlTypeName;
8
9fn api_query(label: &str, name: &str) -> String {
10    format!("api.{label}({name})")
11}
12
13fn to_create_column_def(
14    column: crate::application::schema::CreateTableColumnInput,
15) -> CreateColumnDef {
16    let sql_type = SqlTypeName::parse_declared(&column.data_type);
17    CreateColumnDef {
18        name: column.name,
19        description: None,
20        data_type: column.data_type,
21        sql_type,
22        not_null: column.not_null,
23        default: column.default,
24        generated: None,
25        check: None,
26        compress: column.compress,
27        unique: column.unique,
28        primary_key: column.primary_key,
29        enum_variants: column.enum_variants,
30        array_element: column.array_element,
31        decimal_precision: column.decimal_precision,
32    }
33}
34
35fn to_partition_kind(kind: CreateTablePartitionKind) -> PartitionKind {
36    match kind {
37        CreateTablePartitionKind::Range => PartitionKind::Range,
38        CreateTablePartitionKind::List => PartitionKind::List,
39        CreateTablePartitionKind::Hash => PartitionKind::Hash,
40    }
41}
42
43fn to_partition_spec(spec: CreateTablePartitionSpec) -> PartitionSpec {
44    PartitionSpec {
45        kind: to_partition_kind(spec.kind),
46        column: spec.column,
47    }
48}
49
50impl RuntimeSchemaPort for RedDBRuntime {
51    fn create_table(&self, input: CreateTableInput) -> RedDBResult<RuntimeQueryResult> {
52        let CreateTableInput {
53            name,
54            columns,
55            if_not_exists,
56            default_ttl_ms,
57            context_index_fields,
58            timestamps,
59            partition_by,
60            tenant_by,
61            append_only,
62        } = input;
63        let raw_query = api_query("create_table", &name);
64        let query = CreateTableQuery {
65            collection_model: crate::catalog::CollectionModel::Table,
66            name,
67            description: None,
68            columns: columns.into_iter().map(to_create_column_def).collect(),
69            unique_constraints: Vec::new(),
70            if_not_exists,
71            default_ttl_ms,
72            metrics_rollup_policies: Vec::new(),
73            context_index_fields: context_index_fields.clone(),
74            context_index_enabled: !context_index_fields.is_empty(),
75            timestamps,
76            partition_by: partition_by.map(to_partition_spec),
77            tenant_by,
78            append_only,
79            subscriptions: Vec::new(),
80            analytics_config: Vec::new(),
81            vault_own_master_key: false,
82            ai_policy: None,
83        };
84        RedDBRuntime::execute_create_table(self, &raw_query, &query)
85    }
86
87    fn drop_table(&self, input: DropTableInput) -> RedDBResult<RuntimeQueryResult> {
88        let raw_query = api_query("drop_table", &input.name);
89        let query = DropTableQuery {
90            name: input.name,
91            if_exists: input.if_exists,
92        };
93        RedDBRuntime::execute_drop_table(self, &raw_query, &query)
94    }
95
96    fn create_timeseries(&self, input: CreateTimeSeriesInput) -> RedDBResult<RuntimeQueryResult> {
97        let CreateTimeSeriesInput {
98            name,
99            retention_ms,
100            chunk_size,
101            downsample_policies,
102            if_not_exists,
103        } = input;
104        let raw_query = api_query("create_timeseries", &name);
105        let query = CreateTimeSeriesQuery {
106            name,
107            retention_ms,
108            chunk_size,
109            downsample_policies,
110            if_not_exists,
111            hypertable: None,
112            session_key: None,
113            session_gap_ms: None,
114            // Programmatic create_timeseries follows the automatic
115            // projection policy; SQL callers can opt out with NO COLUMNAR.
116            columnar: true,
117        };
118        RedDBRuntime::execute_create_timeseries(self, &raw_query, &query)
119    }
120
121    fn drop_timeseries(&self, input: DropTimeSeriesInput) -> RedDBResult<RuntimeQueryResult> {
122        let raw_query = api_query("drop_timeseries", &input.name);
123        let query = DropTimeSeriesQuery {
124            name: input.name,
125            if_exists: input.if_exists,
126        };
127        RedDBRuntime::execute_drop_timeseries(self, &raw_query, &query)
128    }
129}