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}