Skip to main content

linkrs_query/query_core/
execution_state.rs

1//! Unified implementation of the status enumeration definition
2//!
3//! This module provides a unified status enumeration for the query execution process, integrating the status definitions that were previously scattered in various locations.
4//! The design adopts a hierarchical state machine to manage states at different levels separately.
5
6use std::fmt;
7
8/// Query execution status - Top-level execution process status
9///
10/// Indicates the lifecycle status of the entire query execution, which is used for query process management.
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
12pub enum QueryExecutionState {
13    /// The query has been created and is waiting to be executed.
14    #[default]
15    Pending,
16    /// The query is currently being executed.
17    Running,
18    /// The query execution has been completed.
19    Completed,
20    /// The query execution failed.
21    Failed,
22    /// The query has been cancelled.
23    Cancelled,
24    /// Query execution timed out.
25    Timeout,
26}
27
28impl QueryExecutionState {
29    /// Check whether the status is terminal.
30    pub fn is_terminal(&self) -> bool {
31        matches!(
32            self,
33            QueryExecutionState::Completed
34                | QueryExecutionState::Failed
35                | QueryExecutionState::Cancelled
36                | QueryExecutionState::Timeout
37        )
38    }
39
40    /// Check whether the status allows cancellation.
41    pub fn can_cancel(&self) -> bool {
42        matches!(
43            self,
44            QueryExecutionState::Pending | QueryExecutionState::Running
45        )
46    }
47
48    /// Get the English description of the status.
49    pub fn description(&self) -> &'static str {
50        match self {
51            QueryExecutionState::Pending => "Pending",
52            QueryExecutionState::Running => "Running",
53            QueryExecutionState::Completed => "Completed",
54            QueryExecutionState::Failed => "Failed",
55            QueryExecutionState::Cancelled => "Cancelled",
56            QueryExecutionState::Timeout => "Timeout",
57        }
58    }
59}
60
61impl fmt::Display for QueryExecutionState {
62    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63        write!(f, "{}", self.description())
64    }
65}
66
67/// Executor State - The operating status of a single executor
68///
69/// Indicates the execution status of a single executor instance, which is used for the management of the executor's lifecycle.
70#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
71pub enum ExecutorState {
72    /// The executor has been created, but the execution has not yet begun.
73    #[default]
74    Initialized,
75    /// The executor is currently in operation (i.e., it is performing its intended function).
76    Executing,
77    /// The executor has completed its execution.
78    Completed,
79    /// The execution of the executor failed.
80    Failed,
81    /// The executor has been cancelled.
82    Cancelled,
83    /// The executor has been paused (for breakpoint debugging purposes).
84    Paused,
85}
86
87impl ExecutorState {
88    /// Check whether the current status allows the transition to the target status.
89    pub fn can_transition_to(&self, target: ExecutorState) -> bool {
90        match (self, target) {
91            // The initial state can be changed to either "Executing", "Failed", or "Cancelled".
92            (ExecutorState::Initialized, ExecutorState::Executing) => true,
93            (ExecutorState::Initialized, ExecutorState::Failed) => true,
94            (ExecutorState::Initialized, ExecutorState::Cancelled) => true,
95            // During the process, the status can be changed to Complete, Failed, Cancel, or Pause.
96            (ExecutorState::Executing, ExecutorState::Completed) => true,
97            (ExecutorState::Executing, ExecutorState::Failed) => true,
98            (ExecutorState::Executing, ExecutorState::Cancelled) => true,
99            (ExecutorState::Executing, ExecutorState::Paused) => true,
100            // A pause can be used to resume the execution of a process, or to cancel or terminate it if it has failed.
101            (ExecutorState::Paused, ExecutorState::Executing) => true,
102            (ExecutorState::Paused, ExecutorState::Failed) => true,
103            (ExecutorState::Paused, ExecutorState::Cancelled) => true,
104            // The final state cannot be changed again.
105            (ExecutorState::Completed, _) => false,
106            (ExecutorState::Failed, _) => false,
107            (ExecutorState::Cancelled, _) => false,
108            _ => false,
109        }
110    }
111
112    /// Get the English description of the status.
113    pub fn description(&self) -> &'static str {
114        match self {
115            ExecutorState::Initialized => "Initialized",
116            ExecutorState::Executing => "Executing",
117            ExecutorState::Completed => "Completed",
118            ExecutorState::Failed => "Failed",
119            ExecutorState::Cancelled => "Cancelled",
120            ExecutorState::Paused => "Paused",
121        }
122    }
123}
124
125impl fmt::Display for ExecutorState {
126    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
127        write!(f, "{}", self.description())
128    }
129}
130
131/// Loop execution state – A status specifically used for loop control
132///
133/// Specifically designed for state management of the LoopExecutor.
134#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
135pub enum LoopExecutionState {
136    /// The loop has not started yet.
137    #[default]
138    NotStarted,
139    /// In the process of cyclic execution…
140    Running { iteration: usize },
141    /// The loop has ended normally.
142    Finished,
143    /// The loop was terminated due to an error.
144    Error(String),
145    /// The loop terminates because the maximum number of iterations has been reached.
146    MaxIterationsReached { max: usize },
147}
148
149impl LoopExecutionState {
150    /// Get the current iteration count.
151    pub fn iteration(&self) -> Option<usize> {
152        match self {
153            LoopExecutionState::Running { iteration } => Some(*iteration),
154            _ => None,
155        }
156    }
157
158    /// Check whether the loop has ended.
159    pub fn is_finished(&self) -> bool {
160        matches!(
161            self,
162            LoopExecutionState::Finished
163                | LoopExecutionState::Error(_)
164                | LoopExecutionState::MaxIterationsReached { .. }
165        )
166    }
167
168    /// Get the English description of the status.
169    pub fn description(&self) -> String {
170        match self {
171            LoopExecutionState::NotStarted => "Not Started".to_string(),
172            LoopExecutionState::Running { iteration } => {
173                format!("Running (iteration {})", iteration)
174            }
175            LoopExecutionState::Finished => "Finished".to_string(),
176            LoopExecutionState::Error(msg) => format!("Error: {}", msg),
177            LoopExecutionState::MaxIterationsReached { max } => {
178                format!("Max iterations reached ({})", max)
179            }
180        }
181    }
182}
183
184impl fmt::Display for LoopExecutionState {
185    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
186        write!(f, "{}", self.description())
187    }
188}
189
190/// Result Line Status – Status of single-line data processing
191///
192/// Indicates the status of the processing result for a single data record.
193#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
194pub enum RowStatus {
195    /// Normal data
196    #[default]
197    Valid,
198    /// The data has been filtered out.
199    Filtered,
200    /// The data is invalid.
201    Invalid,
202    /// The tags have been filtered out.
203    TagFiltered,
204}
205
206impl RowStatus {
207    /// Check whether the data is valid.
208    pub fn is_valid(&self) -> bool {
209        matches!(self, RowStatus::Valid)
210    }
211
212    /// Convert to an integer representation (for compatibility with old code)
213    pub fn to_i32(&self) -> i32 {
214        match self {
215            RowStatus::Valid => 0,
216            RowStatus::Invalid => -1,
217            RowStatus::Filtered => -2,
218            RowStatus::TagFiltered => -3,
219        }
220    }
221}
222
223impl fmt::Display for RowStatus {
224    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
225        match self {
226            RowStatus::Valid => write!(f, "Effective"),
227            RowStatus::Filtered => write!(f, "Filtered"),
228            RowStatus::Invalid => write!(f, "Invalid"),
229            RowStatus::TagFiltered => write!(f, "Tag filtering"),
230        }
231    }
232}
233
234/// Optimization Stage Status - Queries the status of the optimization process
235///
236/// Indicates the stage of the query optimizer's work.
237#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
238pub enum OptimizationState {
239    /// Optimization not started
240    #[default]
241    NotStarted,
242    /// rewrite phase
243    Rewriting,
244    /// Logic optimization phase
245    LogicalOptimizing,
246    /// Physical optimization phase
247    PhysicalOptimizing,
248    /// Optimization completed
249    Completed,
250    /// Optimization Failure
251    Failed,
252}
253
254impl OptimizationState {
255    /// Get the English description of the phase.
256    pub fn description(&self) -> &'static str {
257        match self {
258            OptimizationState::NotStarted => "Not Started",
259            OptimizationState::Rewriting => "Rewriting Phase",
260            OptimizationState::LogicalOptimizing => "Logical Optimizing",
261            OptimizationState::PhysicalOptimizing => "Physical Optimizing",
262            OptimizationState::Completed => "Completed",
263            OptimizationState::Failed => "Failed",
264        }
265    }
266
267    /// Check if it is in the optimization phase
268    pub fn is_optimizing(&self) -> bool {
269        matches!(
270            self,
271            OptimizationState::Rewriting
272                | OptimizationState::LogicalOptimizing
273                | OptimizationState::PhysicalOptimizing
274        )
275    }
276}
277
278impl fmt::Display for OptimizationState {
279    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
280        write!(f, "{}", self.description())
281    }
282}
283
284/// Optimization phase - used to optimize rule classification
285///
286/// Indicates the phase to which the optimization rule belongs and is used to control the order in which the rule is executed.
287#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
288pub enum OptimizationPhase {
289    /// Rewrite Phase - Logical Rewrite Rules
290    Rewrite,
291    /// Logic Optimization Phase - Logic Plan Optimization
292    Logical,
293    /// Physical Optimization Phase - Physical Plan Optimization
294    Physical,
295    /// unknown stage
296    #[default]
297    Unknown,
298}
299
300impl OptimizationPhase {
301    /// Get the English description of the phase.
302    pub fn description(&self) -> &'static str {
303        match self {
304            OptimizationPhase::Rewrite => "Rewrite Phase",
305            OptimizationPhase::Logical => "Logical Optimizing",
306            OptimizationPhase::Physical => "Physical Optimizing",
307            OptimizationPhase::Unknown => "Unknown Phase",
308        }
309    }
310
311    /// Check if it is a logical optimization phase
312    pub fn is_logical(&self) -> bool {
313        matches!(
314            self,
315            OptimizationPhase::Rewrite | OptimizationPhase::Logical
316        )
317    }
318
319    /// Check if it is a physical optimization phase
320    pub fn is_physical(&self) -> bool {
321        matches!(self, OptimizationPhase::Physical)
322    }
323}
324
325impl fmt::Display for OptimizationPhase {
326    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
327        write!(f, "{}", self.description())
328    }
329}
330
331#[cfg(test)]
332mod tests {
333    use super::*;
334
335    #[test]
336    fn test_query_execution_state_transitions() {
337        assert!(!QueryExecutionState::Running.is_terminal());
338        assert!(QueryExecutionState::Completed.is_terminal());
339        assert!(QueryExecutionState::Pending.can_cancel());
340        assert!(!QueryExecutionState::Completed.can_cancel());
341    }
342
343    #[test]
344    fn test_executor_state_transitions() {
345        assert!(ExecutorState::Initialized.can_transition_to(ExecutorState::Executing));
346        assert!(!ExecutorState::Completed.can_transition_to(ExecutorState::Executing));
347        assert!(ExecutorState::Executing.can_transition_to(ExecutorState::Paused));
348        assert!(ExecutorState::Paused.can_transition_to(ExecutorState::Executing));
349    }
350
351    #[test]
352    fn test_loop_execution_state() {
353        let state = LoopExecutionState::Running { iteration: 5 };
354        assert_eq!(state.iteration(), Some(5));
355        assert!(!state.is_finished());
356
357        let finished = LoopExecutionState::Finished;
358        assert!(finished.is_finished());
359    }
360
361    #[test]
362    fn test_row_status_conversion() {
363        assert_eq!(RowStatus::Valid.to_i32(), 0);
364        assert_eq!(RowStatus::Invalid.to_i32(), -1);
365        assert_eq!(RowStatus::Filtered.to_i32(), -2);
366        assert_eq!(RowStatus::TagFiltered.to_i32(), -3);
367    }
368}