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