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        /// Declared type of the target column, as written (e.g. `DECIMAL`).
49        /// The statement declares a real column, so the handler adds it to the
50        /// target's schema — a maintenance write into a strict target is a full
51        /// document write and is rejected on a field the schema does not carry.
52        target_column_type: String,
53        /// Source collection name (lowercased).
54        source_collection: String,
55        /// Join column on the source side (lowercased).
56        join_column: String,
57        /// Value expression (column name or qualified `source.column`, lowercased).
58        value_expr: String,
59    },
60    /// `SET ON CONFLICT <policy_keyword> FOR <constraint_kind_keyword>`
61    ///
62    /// Sets the per-collection, per-constraint-kind conflict resolution policy.
63    SetOnConflict {
64        /// Parsed conflict policy keyword.
65        policy: ConflictPolicyKind,
66        /// Which constraint kind this policy applies to.
67        constraint_kind: ConstraintKindKeyword,
68    },
69}
70
71/// Keyword representation of a conflict resolution policy for DDL.
72#[derive(Debug, Clone, PartialEq)]
73pub enum ConflictPolicyKind {
74    LastWriterWins,
75    RenameSuffix,
76    CascadeDefer,
77    EscalateToDlq,
78}
79
80/// Keyword representation of a constraint kind for DDL.
81#[derive(Debug, Clone, PartialEq)]
82pub enum ConstraintKindKeyword {
83    Unique,
84    ForeignKey,
85    NotNull,
86    Check,
87}
88
89/// Typed sub-operation for `ALTER USER <name> ...`.
90///
91/// Five forms are supported:
92/// - `SET PASSWORD '<pw>'` — change password
93/// - `SET ROLE <role>` — change role
94/// - `MUST CHANGE PASSWORD` — require password change on next login
95/// - `PASSWORD NEVER EXPIRES` — clear expiry date
96/// - `PASSWORD EXPIRES '<iso8601>'` or `PASSWORD EXPIRES IN <N> DAYS` — set expiry
97#[derive(Debug, Clone, PartialEq)]
98pub enum AlterUserOp {
99    /// `SET PASSWORD '<password>'`
100    SetPassword { password: String },
101    /// `SET ROLE <role>`
102    SetRole { role: String },
103    /// `MUST CHANGE PASSWORD`
104    MustChangePassword,
105    /// `PASSWORD NEVER EXPIRES`
106    PasswordNeverExpires,
107    /// `PASSWORD EXPIRES '<iso8601_datetime>'`
108    PasswordExpiresAt { iso8601: String },
109    /// `PASSWORD EXPIRES IN <n> DAYS`
110    PasswordExpiresInDays { days: u32 },
111    /// `SET DEFAULT DATABASE <db_name>`
112    SetDefaultDatabase { db_name: String },
113}
114
115/// Typed sub-operation for `ALTER ROLE <name> ...`.
116///
117/// Three forms are supported:
118/// - `GRANT <perm> ON [FUNCTION] <target>` — grant a permission to the role
119/// - `REVOKE <perm> ON [FUNCTION] <target>` — revoke a permission from the role
120/// - `SET INHERIT <parent>` — update role inheritance (original ALTER ROLE form)
121#[derive(Debug, Clone, PartialEq)]
122pub enum AlterRoleOp {
123    /// `GRANT <perm> ON [FUNCTION] <target>`
124    Grant {
125        /// Permission token, e.g. "READ", "WRITE", "ALL".
126        permission: String,
127        /// "COLLECTION" or "FUNCTION".
128        target_type: String,
129        /// Collection or function name.
130        target_name: String,
131    },
132    /// `REVOKE <perm> ON [FUNCTION] <target>`
133    Revoke {
134        /// Permission token, e.g. "READ", "WRITE", "ALL".
135        permission: String,
136        /// "COLLECTION" or "FUNCTION".
137        target_type: String,
138        /// Collection or function name.
139        target_name: String,
140    },
141    /// `SET INHERIT <parent>`
142    SetInherit {
143        /// Parent role name.
144        parent: String,
145    },
146}