Skip to main content

reddb_server/application/
ports_impls_tree.rs

1use super::*;
2use crate::application::entity::metadata_to_json;
3use reddb_rql::ast::{CreateTreeQuery, DropTreeQuery, TreeCommand, TreeNodeSpec, TreePosition};
4
5fn api_tree_query(label: &str, collection: &str, tree: &str) -> String {
6    format!("api.{label}({collection}.{tree})")
7}
8
9fn tree_position(position: crate::application::TreePositionInput) -> TreePosition {
10    match position {
11        crate::application::TreePositionInput::First => TreePosition::First,
12        crate::application::TreePositionInput::Last => TreePosition::Last,
13        crate::application::TreePositionInput::Index(index) => TreePosition::Index(index),
14    }
15}
16
17fn tree_node_spec(input: crate::application::TreeNodeInput) -> RedDBResult<TreeNodeSpec> {
18    let metadata = input
19        .metadata
20        .into_iter()
21        .map(|(key, value)| {
22            let json = metadata_to_json(&crate::storage::unified::Metadata::with_fields(
23                [(key.clone(), value)].into_iter().collect(),
24            ));
25            let value = json
26                .get(&key)
27                .ok_or_else(|| {
28                    crate::RedDBError::Query(format!(
29                        "failed to convert tree metadata field '{}'",
30                        key
31                    ))
32                })
33                .and_then(crate::application::entity::json_to_storage_value)?;
34            Ok((key, value))
35        })
36        .collect::<RedDBResult<Vec<_>>>()?;
37
38    Ok(TreeNodeSpec {
39        label: input.label,
40        node_type: input.node_type,
41        properties: input.properties,
42        metadata,
43        max_children: input.max_children,
44    })
45}
46
47impl RuntimeTreePort for RedDBRuntime {
48    fn create_tree(&self, input: CreateTreeInput) -> RedDBResult<RuntimeQueryResult> {
49        let raw_query = api_tree_query("create_tree", &input.collection, &input.name);
50        let query = CreateTreeQuery {
51            collection: input.collection,
52            name: input.name,
53            root: tree_node_spec(input.root)?,
54            default_max_children: input.default_max_children,
55            if_not_exists: input.if_not_exists,
56        };
57        RedDBRuntime::execute_create_tree(self, &raw_query, &query)
58    }
59
60    fn drop_tree(&self, input: DropTreeInput) -> RedDBResult<RuntimeQueryResult> {
61        let raw_query = api_tree_query("drop_tree", &input.collection, &input.name);
62        let query = DropTreeQuery {
63            collection: input.collection,
64            name: input.name,
65            if_exists: input.if_exists,
66        };
67        RedDBRuntime::execute_drop_tree(self, &raw_query, &query)
68    }
69
70    fn insert_tree_node(&self, input: InsertTreeNodeInput) -> RedDBResult<RuntimeQueryResult> {
71        let raw_query = api_tree_query("tree_insert", &input.collection, &input.tree_name);
72        let command = TreeCommand::Insert {
73            collection: input.collection,
74            tree_name: input.tree_name,
75            parent_id: input.parent_id,
76            node: tree_node_spec(input.node)?,
77            position: tree_position(input.position),
78        };
79        RedDBRuntime::execute_tree_command(self, &raw_query, &command)
80    }
81
82    fn move_tree_node(&self, input: MoveTreeNodeInput) -> RedDBResult<RuntimeQueryResult> {
83        let raw_query = api_tree_query("tree_move", &input.collection, &input.tree_name);
84        let command = TreeCommand::Move {
85            collection: input.collection,
86            tree_name: input.tree_name,
87            node_id: input.node_id,
88            parent_id: input.parent_id,
89            position: tree_position(input.position),
90        };
91        RedDBRuntime::execute_tree_command(self, &raw_query, &command)
92    }
93
94    fn delete_tree_node(&self, input: DeleteTreeNodeInput) -> RedDBResult<RuntimeQueryResult> {
95        let raw_query = api_tree_query("tree_delete", &input.collection, &input.tree_name);
96        let command = TreeCommand::Delete {
97            collection: input.collection,
98            tree_name: input.tree_name,
99            node_id: input.node_id,
100        };
101        RedDBRuntime::execute_tree_command(self, &raw_query, &command)
102    }
103
104    fn validate_tree(&self, input: ValidateTreeInput) -> RedDBResult<RuntimeQueryResult> {
105        let raw_query = api_tree_query("tree_validate", &input.collection, &input.tree_name);
106        let command = TreeCommand::Validate {
107            collection: input.collection,
108            tree_name: input.tree_name,
109        };
110        RedDBRuntime::execute_tree_command(self, &raw_query, &command)
111    }
112
113    fn rebalance_tree(&self, input: RebalanceTreeInput) -> RedDBResult<RuntimeQueryResult> {
114        let raw_query = api_tree_query("tree_rebalance", &input.collection, &input.tree_name);
115        let command = TreeCommand::Rebalance {
116            collection: input.collection,
117            tree_name: input.tree_name,
118            dry_run: input.dry_run,
119        };
120        RedDBRuntime::execute_tree_command(self, &raw_query, &command)
121    }
122}