linkrs_query/executor/base/
execution_result.rs1use linkrs_core::error::DBError;
6use linkrs_core::types::{SpaceStatus, SpaceSummary};
7use linkrs_core::{DataSet, Value};
8
9#[derive(Debug, Clone)]
13pub enum ExecutionResult {
14 DataSet { data: DataSet },
16 Empty,
18 Success,
20 SpaceSwitched(SpaceSummary),
22 Error(String),
24 ConfigUpdate {
31 module: Option<String>,
32 name: String,
33 value: Value,
34 },
35 ShowConfigs { module: Option<String> },
40}
41
42impl ExecutionResult {
43 pub fn count(&self) -> usize {
45 match self {
46 ExecutionResult::DataSet { data, .. } => data.row_count(),
47 ExecutionResult::Success => 0,
48 ExecutionResult::Empty => 0,
49 ExecutionResult::SpaceSwitched(_) => 0,
50 ExecutionResult::Error(_) => 0,
51 ExecutionResult::ConfigUpdate { .. } => 0,
52 ExecutionResult::ShowConfigs { .. } => 0,
53 }
54 }
55
56 pub fn from_data_set(data: DataSet) -> Self {
58 ExecutionResult::DataSet { data }
59 }
60
61 pub fn to_data_set(&self) -> Option<&DataSet> {
63 match self {
64 ExecutionResult::DataSet { data, .. } => Some(data),
65 _ => None,
66 }
67 }
68
69 pub fn is_space_switched(&self) -> bool {
71 matches!(self, ExecutionResult::SpaceSwitched(_))
72 }
73
74 pub fn space_summary(&self) -> Option<&SpaceSummary> {
76 match self {
77 ExecutionResult::SpaceSwitched(summary) => Some(summary),
78 _ => None,
79 }
80 }
81}
82
83pub type DBResult<T> = Result<T, DBError>;
85
86pub trait IntoExecutionResult {
88 fn into_execution_result(self) -> ExecutionResult;
89}
90
91impl IntoExecutionResult for DataSet {
92 fn into_execution_result(self) -> ExecutionResult {
93 ExecutionResult::DataSet { data: self }
94 }
95}
96
97impl IntoExecutionResult for () {
98 fn into_execution_result(self) -> ExecutionResult {
99 ExecutionResult::Success
100 }
101}
102
103pub fn check_space_writable(space: &SpaceSummary) -> Result<(), ExecutionResult> {
105 match space.status {
106 SpaceStatus::Online => Ok(()),
107 SpaceStatus::Maintenance => Err(ExecutionResult::Error(format!(
108 "Space '{}' is in maintenance mode. Write operations are not allowed.",
109 space.name
110 ))),
111 SpaceStatus::ReadOnly => Err(ExecutionResult::Error(format!(
112 "Space '{}' is in read-only mode. Write operations are not allowed.",
113 space.name
114 ))),
115 SpaceStatus::Offline => Err(ExecutionResult::Error(format!(
116 "Space '{}' is offline. Operations are not allowed.",
117 space.name
118 ))),
119 }
120}
121
122pub fn check_space_accessible(space: &SpaceSummary) -> Result<(), ExecutionResult> {
124 if space.is_accessible() {
125 Ok(())
126 } else {
127 Err(ExecutionResult::Error(format!(
128 "Space '{}' is offline. Operations are not allowed.",
129 space.name
130 )))
131 }
132}
133
134#[cfg(test)]
135mod tests {
136 use super::*;
137 use linkrs_core::types::DataType;
138
139 fn create_test_summary_with_status(status: SpaceStatus) -> SpaceSummary {
140 SpaceSummary {
141 id: 1,
142 name: "test_space".to_string(),
143 vid_type: DataType::String,
144 status,
145 }
146 }
147
148 #[test]
149 fn test_check_space_writable_online() {
150 let summary = create_test_summary_with_status(SpaceStatus::Online);
151 assert!(check_space_writable(&summary).is_ok());
152 }
153
154 #[test]
155 fn test_check_space_writable_maintenance() {
156 let summary = create_test_summary_with_status(SpaceStatus::Maintenance);
157 let result = check_space_writable(&summary);
158 assert!(result.is_err());
159 if let Err(ExecutionResult::Error(msg)) = result {
160 assert!(msg.contains("maintenance mode"));
161 }
162 }
163
164 #[test]
165 fn test_check_space_writable_readonly() {
166 let summary = create_test_summary_with_status(SpaceStatus::ReadOnly);
167 let result = check_space_writable(&summary);
168 assert!(result.is_err());
169 if let Err(ExecutionResult::Error(msg)) = result {
170 assert!(msg.contains("read-only mode"));
171 }
172 }
173
174 #[test]
175 fn test_check_space_writable_offline() {
176 let summary = create_test_summary_with_status(SpaceStatus::Offline);
177 let result = check_space_writable(&summary);
178 assert!(result.is_err());
179 if let Err(ExecutionResult::Error(msg)) = result {
180 assert!(msg.contains("offline"));
181 }
182 }
183
184 #[test]
185 fn test_check_space_accessible() {
186 let online = create_test_summary_with_status(SpaceStatus::Online);
187 let maintenance = create_test_summary_with_status(SpaceStatus::Maintenance);
188 let readonly = create_test_summary_with_status(SpaceStatus::ReadOnly);
189 let offline = create_test_summary_with_status(SpaceStatus::Offline);
190
191 assert!(check_space_accessible(&online).is_ok());
192 assert!(check_space_accessible(&maintenance).is_ok());
193 assert!(check_space_accessible(&readonly).is_ok());
194 assert!(check_space_accessible(&offline).is_err());
195 }
196}