Skip to main content

nodedb_sql/ddl_ast/
alter_ops.rs

1// SPDX-License-Identifier: Apache-2.0
2
3//! Typed sub-operations for `ALTER COLLECTION`, `ALTER USER`, and `ALTER ROLE`.
4
5/// Typed sub-operation for `ALTER COLLECTION <name> ...`.
6///
7/// Each variant corresponds to one ALTER sub-command parsed by
8/// `nodedb-sql/src/ddl_ast/parse/collection.rs`. The handler in
9/// `nodedb/src/control/server/pgwire/ddl/collection/alter/` matches
10/// on this enum instead of rescanning raw SQL.
11#[derive(Debug, Clone, PartialEq)]
12pub enum AlterCollectionOp {
13    /// `ADD [COLUMN] <name> <type> [NOT NULL] [DEFAULT expr]`
14    AddColumn {
15        column_name: String,
16        column_type: String,
17        not_null: bool,
18        default_expr: Option<String>,
19    },
20    /// `DROP COLUMN <name>`
21    DropColumn { column_name: String },
22    /// `RENAME COLUMN <old> TO <new>`
23    RenameColumn { old_name: String, new_name: String },
24    /// `ALTER COLUMN <name> TYPE <type>`
25    AlterColumnType {
26        column_name: String,
27        new_type: String,
28    },
29    /// `OWNER TO <user>`
30    OwnerTo { new_owner: String },
31    /// `SET RETENTION = '<duration>'`
32    SetRetention { value: String },
33    /// `SET APPEND_ONLY`
34    SetAppendOnly,
35    /// `SET LAST_VALUE_CACHE = TRUE|FALSE`
36    SetLastValueCache { enabled: bool },
37    /// `SET LEGAL_HOLD = TRUE|FALSE TAG '<tag>'`
38    SetLegalHold { enabled: bool, tag: String },
39    /// `ADD [COLUMN] <target_column> ... AS MATERIALIZED_SUM SOURCE <source_collection>
40    /// ON <join_column> VALUE <value_expr>` — fully parsed by
41    /// `nodedb-sql`; the handler receives typed fields and never
42    /// rescans raw SQL.
43    AddMaterializedSum {
44        /// Target collection name (lowercased).
45        target_collection: String,
46        /// Target column name to hold the sum (lowercased).
47        target_column: String,
48        /// Source collection name (lowercased).
49        source_collection: String,
50        /// Join column on the source side (lowercased).
51        join_column: String,
52        /// Value expression (column name or qualified `source.column`, lowercased).
53        value_expr: String,
54    },
55    /// `SET ON CONFLICT <policy_keyword> FOR <constraint_kind_keyword>`
56    ///
57    /// Sets the per-collection, per-constraint-kind conflict resolution policy.
58    SetOnConflict {
59        /// Parsed conflict policy keyword.
60        policy: ConflictPolicyKind,
61        /// Which constraint kind this policy applies to.
62        constraint_kind: ConstraintKindKeyword,
63    },
64}
65
66/// Keyword representation of a conflict resolution policy for DDL.
67#[derive(Debug, Clone, PartialEq)]
68pub enum ConflictPolicyKind {
69    LastWriterWins,
70    RenameSuffix,
71    CascadeDefer,
72    EscalateToDlq,
73}
74
75/// Keyword representation of a constraint kind for DDL.
76#[derive(Debug, Clone, PartialEq)]
77pub enum ConstraintKindKeyword {
78    Unique,
79    ForeignKey,
80    NotNull,
81    Check,
82}
83
84/// Typed sub-operation for `ALTER USER <name> ...`.
85///
86/// Five forms are supported:
87/// - `SET PASSWORD '<pw>'` — change password
88/// - `SET ROLE <role>` — change role
89/// - `MUST CHANGE PASSWORD` — require password change on next login
90/// - `PASSWORD NEVER EXPIRES` — clear expiry date
91/// - `PASSWORD EXPIRES '<iso8601>'` or `PASSWORD EXPIRES IN <N> DAYS` — set expiry
92#[derive(Debug, Clone, PartialEq)]
93pub enum AlterUserOp {
94    /// `SET PASSWORD '<password>'`
95    SetPassword { password: String },
96    /// `SET ROLE <role>`
97    SetRole { role: String },
98    /// `MUST CHANGE PASSWORD`
99    MustChangePassword,
100    /// `PASSWORD NEVER EXPIRES`
101    PasswordNeverExpires,
102    /// `PASSWORD EXPIRES '<iso8601_datetime>'`
103    PasswordExpiresAt { iso8601: String },
104    /// `PASSWORD EXPIRES IN <n> DAYS`
105    PasswordExpiresInDays { days: u32 },
106    /// `SET DEFAULT DATABASE <db_name>`
107    SetDefaultDatabase { db_name: String },
108}
109
110/// Typed sub-operation for `ALTER ROLE <name> ...`.
111///
112/// Three forms are supported:
113/// - `GRANT <perm> ON [FUNCTION] <target>` — grant a permission to the role
114/// - `REVOKE <perm> ON [FUNCTION] <target>` — revoke a permission from the role
115/// - `SET INHERIT <parent>` — update role inheritance (original ALTER ROLE form)
116#[derive(Debug, Clone, PartialEq)]
117pub enum AlterRoleOp {
118    /// `GRANT <perm> ON [FUNCTION] <target>`
119    Grant {
120        /// Permission token, e.g. "READ", "WRITE", "ALL".
121        permission: String,
122        /// "COLLECTION" or "FUNCTION".
123        target_type: String,
124        /// Collection or function name.
125        target_name: String,
126    },
127    /// `REVOKE <perm> ON [FUNCTION] <target>`
128    Revoke {
129        /// Permission token, e.g. "READ", "WRITE", "ALL".
130        permission: String,
131        /// "COLLECTION" or "FUNCTION".
132        target_type: String,
133        /// Collection or function name.
134        target_name: String,
135    },
136    /// `SET INHERIT <parent>`
137    SetInherit {
138        /// Parent role name.
139        parent: String,
140    },
141}