Skip to main content

linkrs_query/executor/streaming/operators/spec/
ddl.rs

1//! Immutable configuration for DDL operators and schema/user manage payloads.
2
3use crate::parser::ast::stmt::PurgeTarget;
4use linkrs_core::metadata::MacroParamDef;
5use linkrs_core::types::expr::Expression;
6use linkrs_core::types::user::PasswordInfo;
7use linkrs_core::types::PropertyDef;
8
9/// Migrate action kind.
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum MigrateAction {
12    MigrateSpace,
13}
14
15/// Space DDL command payload.
16#[derive(Debug, Clone)]
17pub enum SpaceManageCommand {
18    Create {
19        space_name: String,
20        vid_type: String,
21        comment: Option<String>,
22    },
23    Drop {
24        space_name: String,
25        if_exists: bool,
26    },
27    Desc {
28        space_name: String,
29    },
30    Show,
31    ShowCreate {
32        space_name: String,
33    },
34    Switch {
35        space_name: String,
36    },
37    Clear {
38        space_name: String,
39    },
40    Checkpoint,
41    ExportDatabase {
42        path: String,
43    },
44    ImportDatabase {
45        path: String,
46    },
47    AttachDatabase {
48        alias: String,
49        path: String,
50        db_type: Option<String>,
51    },
52    DetachDatabase {
53        alias: String,
54    },
55    PurgeExpired {
56        space_name: String,
57        target: Option<PurgeTarget>,
58    },
59}
60
61/// Tag DDL command payload.
62#[derive(Debug, Clone)]
63pub enum TagManageCommand {
64    Create {
65        tag_name: String,
66        properties: Vec<PropertyDef>,
67        if_not_exists: bool,
68        ttl_duration: Option<i64>,
69        ttl_col: Option<String>,
70    },
71    Alter {
72        tag_name: String,
73        additions: Vec<PropertyDef>,
74        deletions: Vec<String>,
75        changes: Vec<PropertyRename>,
76        new_comment: Option<String>,
77    },
78    Rename {
79        old_name: String,
80        new_name: String,
81    },
82    Desc {
83        tag_name: String,
84    },
85    Drop {
86        tag_names: Vec<String>,
87        if_exists: bool,
88    },
89    Show,
90    ShowCreate {
91        tag_name: String,
92    },
93}
94
95/// Edge DDL command payload.
96#[derive(Debug, Clone)]
97pub enum EdgeManageCommand {
98    Create {
99        edge_name: String,
100        properties: Vec<PropertyDef>,
101        src_tag_name: Option<String>,
102        dst_tag_name: Option<String>,
103        if_not_exists: bool,
104        ttl_duration: Option<i64>,
105        ttl_col: Option<String>,
106    },
107    Alter {
108        edge_name: String,
109        additions: Vec<PropertyDef>,
110        deletions: Vec<String>,
111        changes: Vec<PropertyRename>,
112        new_comment: Option<String>,
113    },
114    Rename {
115        old_name: String,
116        new_name: String,
117    },
118    UpdateEndpoints {
119        edge_name: String,
120        src_tag_name: String,
121        dst_tag_name: String,
122        clear_constraint: bool,
123    },
124    Desc {
125        edge_name: String,
126    },
127    Drop {
128        edge_names: Vec<String>,
129        if_exists: bool,
130    },
131    Show,
132    ShowCreate {
133        edge_name: String,
134    },
135}
136
137/// Sequence DDL command payload.
138#[derive(Debug, Clone)]
139pub enum SequenceManageCommand {
140    Create {
141        seq_name: String,
142        start: Option<i64>,
143        increment: Option<i64>,
144        min_value: Option<i64>,
145        max_value: Option<i64>,
146        cycle: bool,
147        if_not_exists: bool,
148    },
149    Alter {
150        seq_name: String,
151        increment: Option<i64>,
152        min_value: Option<i64>,
153        max_value: Option<i64>,
154        cycle: Option<bool>,
155    },
156    Drop {
157        seq_name: String,
158        if_exists: bool,
159    },
160}
161
162/// Macro DDL command payload.
163///
164/// The body is the parsed macro template; the binder expands macro calls
165/// before planning, so the executor only stores and lists definitions.
166#[derive(Debug, Clone)]
167pub enum MacroManageCommand {
168    Create {
169        macro_name: String,
170        params: Vec<MacroParamDef>,
171        body: Expression,
172        if_not_exists: bool,
173    },
174    Drop {
175        macro_name: String,
176        if_exists: bool,
177    },
178}
179
180/// Type DDL command payload.
181#[derive(Debug, Clone)]
182pub enum TypeManageCommand {
183    Create {
184        type_name: String,
185        underlying_type: String,
186        if_not_exists: bool,
187    },
188    Drop {
189        type_name: String,
190        if_exists: bool,
191    },
192}
193
194/// Index DDL command payload.
195#[derive(Debug, Clone)]
196pub enum IndexManageCommand {
197    CreateTagIndex {
198        index_name: String,
199        target_name: String,
200        properties: Vec<String>,
201    },
202    DropTagIndex {
203        index_name: String,
204        if_exists: bool,
205    },
206    DescTagIndex {
207        index_name: String,
208    },
209    ShowTagIndexes,
210    RebuildTagIndex {
211        index_name: String,
212    },
213    CreateEdgeIndex {
214        index_name: String,
215        target_name: String,
216        properties: Vec<String>,
217    },
218    DropEdgeIndex {
219        index_name: String,
220        if_exists: bool,
221    },
222    DescEdgeIndex {
223        index_name: String,
224    },
225    ShowEdgeIndexes,
226    RebuildEdgeIndex {
227        index_name: String,
228    },
229    ShowIndexes,
230    ShowCreateIndex {
231        index_name: String,
232    },
233}
234
235/// User DDL command payload.
236#[derive(Debug, Clone)]
237pub enum UserManageCommand {
238    Create {
239        username: String,
240        password: String,
241        if_not_exists: bool,
242    },
243    Alter {
244        username: String,
245        new_password: Option<String>,
246        is_locked: Option<bool>,
247        /// Retained password-history depth applied on rotation; zero clears.
248        history_limit: usize,
249    },
250    Drop {
251        username: String,
252        if_exists: bool,
253    },
254    ChangePassword {
255        password_info: PasswordInfo,
256    },
257    GrantRole {
258        username: String,
259        space_name: String,
260        role: String,
261    },
262    RevokeRole {
263        username: String,
264        space_name: String,
265        role: String,
266    },
267    ShowUsers,
268    ShowRoles {
269        /// Space-name filter from `SHOW ROLES IN <space>`; empty means all spaces.
270        space_name: String,
271    },
272    DescribeUser {
273        username: String,
274    },
275}
276
277/// Property rename within ALTER TAG (executor consumes only old/new names).
278#[derive(Debug, Clone)]
279pub struct PropertyRename {
280    pub old_name: String,
281    pub new_name: String,
282}
283
284/// Immutable config for DDL operators.
285#[derive(Debug, Clone)]
286pub enum DdlSpec {
287    SpaceManage {
288        command: SpaceManageCommand,
289    },
290    TagManage {
291        space_name: String,
292        command: TagManageCommand,
293    },
294    EdgeManage {
295        space_name: String,
296        command: EdgeManageCommand,
297    },
298    IndexManage {
299        space_name: String,
300        command: IndexManageCommand,
301    },
302    DeleteIndex {
303        space_name: String,
304        index_name: String,
305    },
306    UserManage {
307        command: UserManageCommand,
308    },
309    ShowStats {
310        space_name: String,
311    },
312    ShowConfigs {
313        space_name: String,
314    },
315    ShowQueries {
316        space_name: String,
317    },
318    ShowSessions {
319        space_name: String,
320    },
321    ShowFunctions {
322        space_name: String,
323    },
324    ShowGraphs {
325        space_name: String,
326    },
327    ShowMacros {
328        space_name: String,
329    },
330    ShowAttachedDatabases {
331        space_name: String,
332    },
333    ShowExtensions {
334        space_name: String,
335    },
336    LoadFrom {
337        space_name: String,
338        source_kind: String,
339        source_value: String,
340        func_name: Option<String>,
341        func_args_json: Option<String>,
342        options: Vec<(String, String)>,
343        col_names: Vec<String>,
344        headers: Vec<String>,
345    },
346    InQueryCall {
347        space_name: String,
348        func_name: String,
349        args_json: String,
350        yield_items: Vec<(String, String)>,
351        col_names: Vec<String>,
352    },
353    Analyze {
354        space_name: String,
355    },
356    Migrate {
357        space_name: String,
358        action: MigrateAction,
359        migration_data: Option<String>,
360    },
361    MigratePlan {
362        space_name: String,
363        label: String,
364        is_edge: bool,
365        from_version: u64,
366        to_version: u64,
367    },
368    MigrateRun {
369        plan_json: String,
370    },
371    MigrateRollback {
372        plan_json: String,
373    },
374    SequenceManage {
375        command: SequenceManageCommand,
376    },
377    MacroManage {
378        command: MacroManageCommand,
379    },
380    TypeManage {
381        command: TypeManageCommand,
382    },
383}
384
385impl SpaceManageCommand {
386    /// Whether the command mutates stored state.
387    ///
388    /// Describe/show variants only read schema metadata; switch only flips
389    /// session-level space routing.
390    pub fn is_write(&self) -> bool {
391        match self {
392            Self::Create { .. }
393            | Self::Drop { .. }
394            | Self::Clear { .. }
395            | Self::Checkpoint
396            | Self::PurgeExpired { .. }
397            | Self::ExportDatabase { .. }
398            | Self::ImportDatabase { .. } => true,
399            // Attach/Detach only mutate the in-memory attached-database
400            // catalog, not storage, so they must not demand a write
401            // transaction scope.
402            Self::AttachDatabase { .. } | Self::DetachDatabase { .. } => false,
403            Self::Desc { .. } | Self::Show | Self::ShowCreate { .. } | Self::Switch { .. } => false,
404        }
405    }
406}
407
408impl TagManageCommand {
409    /// Whether the command mutates stored state.
410    pub fn is_write(&self) -> bool {
411        match self {
412            Self::Create { .. } | Self::Alter { .. } | Self::Rename { .. } | Self::Drop { .. } => {
413                true
414            }
415            Self::Desc { .. } | Self::Show | Self::ShowCreate { .. } => false,
416        }
417    }
418}
419
420impl EdgeManageCommand {
421    /// Whether the command mutates stored state.
422    pub fn is_write(&self) -> bool {
423        match self {
424            Self::Create { .. }
425            | Self::Alter { .. }
426            | Self::Rename { .. }
427            | Self::UpdateEndpoints { .. }
428            | Self::Drop { .. } => true,
429            Self::Desc { .. } | Self::Show | Self::ShowCreate { .. } => false,
430        }
431    }
432}
433
434impl SequenceManageCommand {
435    /// Whether the command mutates stored state.
436    pub fn is_write(&self) -> bool {
437        match self {
438            Self::Create { .. } | Self::Alter { .. } | Self::Drop { .. } => true,
439        }
440    }
441}
442
443impl MacroManageCommand {
444    /// Whether the command mutates stored state.
445    pub fn is_write(&self) -> bool {
446        match self {
447            Self::Create { .. } | Self::Drop { .. } => true,
448        }
449    }
450}
451
452impl TypeManageCommand {
453    /// Whether the command mutates stored state.
454    pub fn is_write(&self) -> bool {
455        match self {
456            Self::Create { .. } | Self::Drop { .. } => true,
457        }
458    }
459}
460
461impl IndexManageCommand {
462    /// Whether the command mutates stored state.
463    ///
464    /// Describe/show variants only read index metadata.
465    pub fn is_write(&self) -> bool {
466        match self {
467            Self::CreateTagIndex { .. }
468            | Self::DropTagIndex { .. }
469            | Self::RebuildTagIndex { .. }
470            | Self::CreateEdgeIndex { .. }
471            | Self::DropEdgeIndex { .. }
472            | Self::RebuildEdgeIndex { .. } => true,
473            Self::DescTagIndex { .. }
474            | Self::ShowTagIndexes
475            | Self::DescEdgeIndex { .. }
476            | Self::ShowEdgeIndexes
477            | Self::ShowIndexes
478            | Self::ShowCreateIndex { .. } => false,
479        }
480    }
481}
482
483impl UserManageCommand {
484    /// Whether the command mutates the user/privilege store.
485    ///
486    /// Show/describe variants only read through the auth reader.
487    pub fn is_write(&self) -> bool {
488        match self {
489            Self::Create { .. }
490            | Self::Alter { .. }
491            | Self::Drop { .. }
492            | Self::ChangePassword { .. }
493            | Self::GrantRole { .. }
494            | Self::RevokeRole { .. } => true,
495            Self::ShowUsers | Self::ShowRoles { .. } | Self::DescribeUser { .. } => false,
496        }
497    }
498}
499
500impl DdlSpec {
501    /// Whether the spec mutates stored state.
502    ///
503    /// Read-only variants (describe/show) run on the statement-level read
504    /// snapshot and must not require a write transaction scope.
505    pub fn is_write(&self) -> bool {
506        match self {
507            Self::SpaceManage { command } => command.is_write(),
508            Self::TagManage { command, .. } => command.is_write(),
509            Self::EdgeManage { command, .. } => command.is_write(),
510            Self::IndexManage { command, .. } => command.is_write(),
511            Self::DeleteIndex { .. } => true,
512            Self::UserManage { command } => command.is_write(),
513            Self::ShowStats { .. }
514            | Self::ShowConfigs { .. }
515            | Self::ShowQueries { .. }
516            | Self::ShowSessions { .. }
517            | Self::ShowFunctions { .. }
518            | Self::ShowGraphs { .. }
519            | Self::ShowMacros { .. }
520            | Self::ShowAttachedDatabases { .. }
521            | Self::ShowExtensions { .. }
522            | Self::LoadFrom { .. }
523            | Self::InQueryCall { .. }
524            | Self::Analyze { .. } => false,
525            Self::Migrate { .. }
526            | Self::MigratePlan { .. }
527            | Self::MigrateRun { .. }
528            | Self::MigrateRollback { .. } => true,
529            Self::SequenceManage { command } => command.is_write(),
530            Self::MacroManage { command } => command.is_write(),
531            Self::TypeManage { command } => command.is_write(),
532        }
533    }
534}