Skip to main content

uqa_sql/plan/
statement.rs

1//
2// Unified Query Algebra
3//
4// Copyright (c) 2023-2026 Cognica, Inc.
5//
6
7//! Top-level SQL statement lowering and command naming.
8
9use super::model::NoRegisteredAggregates;
10use super::query::{lower_assignments, lower_ctes, lower_merge_when, lower_targets};
11use super::rewrite::{rewrite_command_scalars, rewrite_query_scalars};
12use super::scalar::lower_scalar_expression;
13use super::{
14    AggregateClassifier, CommandPlan, ConflictActionPlan, ConflictPlan, DeletePlan, ExpressionPlan,
15    InsertPlan, MergePlan, ProjectionPlan, QueryPlan, RelationalPlan, ScalarExpr, SourcePlan,
16    Statement, UnifiedPlan, UpdatePlan,
17};
18
19impl UnifiedPlan {
20    /// Lower a statement using only the built-in SQL aggregate catalogue.
21    #[must_use]
22    pub fn lower(statement: Statement) -> Self {
23        Self::lower_with(statement, &NoRegisteredAggregates)
24    }
25
26    /// Lower a statement with engine-local aggregate classification.
27    #[must_use]
28    #[expect(
29        clippy::too_many_lines,
30        reason = "plan lowering preserves exhaustive variants and structural identities"
31    )]
32    pub fn lower_with(statement: Statement, aggregates: &dyn AggregateClassifier) -> Self {
33        match statement {
34            Statement::Select(query) => {
35                Self::Query(Box::new(QueryPlan::lower_with(*query, aggregates)))
36            }
37            Statement::Values { rows } => {
38                let mut subqueries = Vec::new();
39                let rows = rows
40                    .into_iter()
41                    .map(|row| {
42                        row.into_iter()
43                            .map(|expr| lower_scalar_expression(expr, aggregates, &mut subqueries))
44                            .collect()
45                    })
46                    .collect();
47                Self::Query(Box::new(QueryPlan {
48                    relations_bound: false,
49                    ctes: Vec::new(),
50                    root: RelationalPlan::Values { rows, subqueries },
51                }))
52            }
53            Statement::CreateTable(value) => {
54                Self::Command(Box::new(CommandPlan::CreateTable(Box::new(value))))
55            }
56            Statement::CreateTableIfNotExists(value) => {
57                Self::Command(Box::new(CommandPlan::CreateTableIfNotExists(value)))
58            }
59            Statement::CreateIndex(value) => {
60                Self::Command(Box::new(CommandPlan::CreateIndex(value)))
61            }
62            Statement::RenameIndex(value) => {
63                Self::Command(Box::new(CommandPlan::RenameIndex(value)))
64            }
65            Statement::Insert(statement) => {
66                let ctes = lower_ctes(&statement.with, aggregates);
67                let source = statement
68                    .select_source
69                    .map(|query| Box::new(QueryPlan::lower_with(*query, aggregates)));
70                let mut subqueries = Vec::new();
71                let rows = statement
72                    .rows
73                    .into_iter()
74                    .map(|row| {
75                        row.into_iter()
76                            .map(|expr| lower_scalar_expression(expr, aggregates, &mut subqueries))
77                            .collect()
78                    })
79                    .collect();
80                let on_conflict = statement.on_conflict.map(|conflict| {
81                    let action = match conflict.action {
82                        crate::ast::OnConflictAction::Nothing => ConflictActionPlan::Nothing,
83                        crate::ast::OnConflictAction::Update {
84                            assignments,
85                            r#where,
86                        } => ConflictActionPlan::Update {
87                            assignments: lower_assignments(
88                                assignments,
89                                aggregates,
90                                &mut subqueries,
91                            ),
92                            predicate: r#where.map(|expr| {
93                                Box::new(lower_scalar_expression(
94                                    *expr,
95                                    aggregates,
96                                    &mut subqueries,
97                                ))
98                            }),
99                        },
100                    };
101                    ConflictPlan {
102                        predicate: conflict.predicate.map(|expr| {
103                            Box::new(lower_scalar_expression(*expr, aggregates, &mut subqueries))
104                        }),
105                        constraint: conflict.constraint,
106                        conflict_columns: conflict.conflict_columns,
107                        expressions: conflict
108                            .expressions
109                            .into_iter()
110                            .map(|expr| lower_scalar_expression(expr, aggregates, &mut subqueries))
111                            .collect(),
112                        action,
113                    }
114                });
115                let returning = statement
116                    .returning
117                    .into_iter()
118                    .map(|projection| {
119                        ProjectionPlan::lower_with(projection, aggregates, &mut subqueries)
120                    })
121                    .collect();
122                Self::Command(Box::new(CommandPlan::Insert(Box::new(InsertPlan {
123                    table: statement.table,
124                    target_relation_bound: statement.target_relation_bound,
125                    relations_bound: false,
126                    statement_privilege_subject: None,
127                    target_privilege_subject: None,
128                    target_qualifier: statement.target_qualifier,
129                    target_alias: statement.target_alias,
130                    include_descendants: statement.include_descendants,
131                    columns: lower_targets(statement.columns, aggregates, &mut subqueries),
132                    overriding: statement.overriding,
133                    ctes,
134                    rows,
135                    source,
136                    on_conflict,
137                    returning,
138                    returning_aliases: statement.returning_aliases,
139                    subqueries,
140                    view_checks: Vec::new(),
141                    view_rule_relations: Vec::new(),
142                    view_rule_insert_plans: Vec::new(),
143                    view_rule_returning: None,
144                }))))
145            }
146            Statement::Update(statement) => {
147                let ctes = lower_ctes(&statement.with, aggregates);
148                let mut subqueries = Vec::new();
149                let source = statement
150                    .from
151                    .map(|from| SourcePlan::lower_with(from, aggregates, &mut subqueries));
152                let assignments =
153                    lower_assignments(statement.assignments, aggregates, &mut subqueries);
154                let predicate = statement
155                    .r#where
156                    .map(|expr| lower_scalar_expression(expr, aggregates, &mut subqueries));
157                let returning = statement
158                    .returning
159                    .into_iter()
160                    .map(|projection| {
161                        ProjectionPlan::lower_with(projection, aggregates, &mut subqueries)
162                    })
163                    .collect();
164                Self::Command(Box::new(CommandPlan::Update(Box::new(UpdatePlan {
165                    table: statement.table,
166                    target_relation_bound: statement.target_relation_bound,
167                    relations_bound: false,
168                    statement_privilege_subject: None,
169                    target_privilege_subject: None,
170                    target_qualifier: statement.target_qualifier,
171                    target_alias: statement.target_alias,
172                    include_descendants: statement.include_descendants,
173                    assignments,
174                    predicate,
175                    ctes,
176                    source: source.map(Box::new),
177                    returning,
178                    returning_aliases: statement.returning_aliases,
179                    subqueries,
180                    view_checks: Vec::new(),
181                    view_rule_relations: Vec::new(),
182                    view_rule_update_plans: Vec::new(),
183                    view_rule_returning: None,
184                }))))
185            }
186            Statement::Delete(statement) => {
187                let ctes = lower_ctes(&statement.with, aggregates);
188                let mut subqueries = Vec::new();
189                let source = statement
190                    .using
191                    .map(|from| SourcePlan::lower_with(from, aggregates, &mut subqueries));
192                let predicate = statement
193                    .r#where
194                    .map(|expr| lower_scalar_expression(expr, aggregates, &mut subqueries));
195                let returning = statement
196                    .returning
197                    .into_iter()
198                    .map(|projection| {
199                        ProjectionPlan::lower_with(projection, aggregates, &mut subqueries)
200                    })
201                    .collect();
202                Self::Command(Box::new(CommandPlan::Delete(Box::new(DeletePlan {
203                    table: statement.table,
204                    target_relation_bound: statement.target_relation_bound,
205                    relations_bound: false,
206                    statement_privilege_subject: None,
207                    target_privilege_subject: None,
208                    target_qualifier: statement.target_qualifier,
209                    target_alias: statement.target_alias,
210                    include_descendants: statement.include_descendants,
211                    predicate,
212                    ctes,
213                    source: source.map(Box::new),
214                    returning,
215                    returning_aliases: statement.returning_aliases,
216                    subqueries,
217                    view_rule_relations: Vec::new(),
218                    view_rule_returning: None,
219                }))))
220            }
221            Statement::Drop(value) => Self::Command(Box::new(CommandPlan::Drop(value))),
222            Statement::AlterTable(value) => {
223                Self::Command(Box::new(CommandPlan::AlterTable(Box::new(value))))
224            }
225            Statement::AlterForeignTable(value) => {
226                Self::Command(Box::new(CommandPlan::AlterForeignTable(value)))
227            }
228            Statement::AlterView(value) => Self::Command(Box::new(CommandPlan::AlterView(value))),
229            Statement::CreateView {
230                name,
231                column_names,
232                body,
233                or_replace,
234                persistence,
235                options,
236            } => {
237                let query = Box::new(QueryPlan::lower_with(*body, aggregates));
238                Self::Command(Box::new(CommandPlan::CreateView {
239                    name,
240                    column_names,
241                    query,
242                    or_replace,
243                    persistence,
244                    options,
245                }))
246            }
247            Statement::CreateMaterializedView {
248                name,
249                column_names,
250                if_not_exists,
251                with_no_data,
252                options,
253                body,
254            } => Self::Command(Box::new(CommandPlan::CreateMaterializedView {
255                name,
256                column_names,
257                if_not_exists,
258                with_no_data,
259                options,
260                query: Box::new(QueryPlan::lower_with(*body, aggregates)),
261            })),
262            Statement::RefreshMaterializedView {
263                name,
264                concurrently,
265                with_no_data,
266            } => Self::Command(Box::new(CommandPlan::RefreshMaterializedView {
267                name,
268                concurrently,
269                with_no_data,
270            })),
271            Statement::CreateSchema {
272                name,
273                if_not_exists,
274                authorization,
275            } => Self::Command(Box::new(CommandPlan::CreateSchema {
276                name,
277                if_not_exists,
278                authorization,
279            })),
280            Statement::AlterSchemaOwner { name, new_owner } => {
281                Self::Command(Box::new(CommandPlan::AlterSchemaOwner { name, new_owner }))
282            }
283            Statement::RenameSchema { name, new_name } => {
284                Self::Command(Box::new(CommandPlan::RenameSchema { name, new_name }))
285            }
286            Statement::Notify { channel, payload } => {
287                Self::Command(Box::new(CommandPlan::Notify { channel, payload }))
288            }
289            Statement::Listen { channel } => {
290                Self::Command(Box::new(CommandPlan::Listen { channel }))
291            }
292            Statement::Unlisten { channel } => {
293                Self::Command(Box::new(CommandPlan::Unlisten { channel }))
294            }
295            Statement::SetVariable {
296                name,
297                value,
298                local,
299                is_default,
300            } => Self::Command(Box::new(CommandPlan::SetVariable {
301                name,
302                value,
303                local,
304                is_default,
305            })),
306            Statement::ResetVariable { name } => {
307                Self::Command(Box::new(CommandPlan::ResetVariable { name }))
308            }
309            Statement::ResetAllVariables => Self::Command(Box::new(CommandPlan::ResetAllVariables)),
310            Statement::SetConstraints {
311                constraints,
312                deferred,
313            } => Self::Command(Box::new(CommandPlan::SetConstraints {
314                constraints,
315                deferred,
316            })),
317            Statement::ShowVariable { name } => {
318                Self::Command(Box::new(CommandPlan::ShowVariable { name }))
319            }
320            Statement::Discard { target } => {
321                Self::Command(Box::new(CommandPlan::Discard { target }))
322            }
323            Statement::Load { library } => Self::Command(Box::new(CommandPlan::Load { library })),
324            Statement::Explain {
325                analyze,
326                verbose,
327                format,
328                body,
329            } => Self::Command(Box::new(CommandPlan::Explain {
330                analyze,
331                verbose,
332                format,
333                body: Box::new(Self::lower_with(*body, aggregates)),
334            })),
335            Statement::Analyze { table } => Self::Command(Box::new(CommandPlan::Analyze { table })),
336            Statement::Vacuum(vacuum) => Self::Command(Box::new(CommandPlan::Vacuum(vacuum))),
337            Statement::LockTable(lock) => Self::Command(Box::new(CommandPlan::LockTable(lock))),
338            Statement::Truncate {
339                tables,
340                cascade,
341                restart_identity,
342            } => Self::Command(Box::new(CommandPlan::Truncate {
343                tables,
344                cascade,
345                restart_identity,
346            })),
347            Statement::Transaction(value) => {
348                Self::Command(Box::new(CommandPlan::Transaction(value)))
349            }
350            Statement::DeclareCursor(cursor) => {
351                Self::Command(Box::new(CommandPlan::DeclareCursor {
352                    name: cursor.name,
353                    binary: cursor.binary,
354                    scroll: cursor.scroll,
355                    hold: cursor.hold,
356                    query: Box::new(QueryPlan::lower_with(*cursor.query, aggregates)),
357                }))
358            }
359            Statement::FetchCursor(cursor) => {
360                Self::Command(Box::new(CommandPlan::FetchCursor(cursor)))
361            }
362            Statement::CloseCursor { name } => {
363                Self::Command(Box::new(CommandPlan::CloseCursor { name }))
364            }
365            Statement::CreateSequence(value) => {
366                Self::Command(Box::new(CommandPlan::CreateSequence(value)))
367            }
368            Statement::CreateEnum(value) => Self::Command(Box::new(CommandPlan::CreateEnum(value))),
369            Statement::CreateCompositeType(value) => {
370                Self::Command(Box::new(CommandPlan::CreateCompositeType(value)))
371            }
372            Statement::AlterEnum(value) => Self::Command(Box::new(CommandPlan::AlterEnum(value))),
373            Statement::AlterTypeObject(value) => {
374                Self::Command(Box::new(CommandPlan::AlterTypeObject(value)))
375            }
376            Statement::GrantType(value) => Self::Command(Box::new(CommandPlan::GrantType(value))),
377            Statement::CreateDomain(value) => {
378                Self::Command(Box::new(CommandPlan::CreateDomain(value)))
379            }
380            Statement::AlterDomain(value) => {
381                Self::Command(Box::new(CommandPlan::AlterDomain(value)))
382            }
383            Statement::AlterSequence(value) => {
384                Self::Command(Box::new(CommandPlan::AlterSequence(value)))
385            }
386            Statement::CreateTableAs {
387                name,
388                if_not_exists,
389                column_names,
390                with_no_data,
391                select_into,
392                persistence,
393                on_commit,
394                body,
395            } => Self::Command(Box::new(CommandPlan::CreateTableAs {
396                name,
397                if_not_exists,
398                column_names,
399                with_no_data,
400                select_into,
401                persistence,
402                on_commit,
403                query: Box::new(QueryPlan::lower_with(*body, aggregates)),
404            })),
405            Statement::Prepare {
406                name,
407                parameter_types,
408                body,
409            } => {
410                let body = Box::new(Self::lower_with(*body, aggregates));
411                Self::Command(Box::new(CommandPlan::Prepare {
412                    name,
413                    parameter_types,
414                    body,
415                }))
416            }
417            Statement::Execute { name, params } => Self::Command(Box::new(CommandPlan::Execute {
418                name,
419                params: params
420                    .into_iter()
421                    .map(|expr| ExpressionPlan::lower_with(expr, aggregates))
422                    .collect(),
423            })),
424            Statement::Deallocate { name } => {
425                Self::Command(Box::new(CommandPlan::Deallocate { name }))
426            }
427            Statement::CreateForeignWrapper(value) => {
428                Self::Command(Box::new(CommandPlan::CreateForeignWrapper(value)))
429            }
430            Statement::CreateForeignServer(value) => {
431                Self::Command(Box::new(CommandPlan::CreateForeignServer(value)))
432            }
433            Statement::CreateForeignTable(value) => {
434                Self::Command(Box::new(CommandPlan::CreateForeignTable(value)))
435            }
436            Statement::CreateForeignTableDefinition(value) => {
437                Self::Command(Box::new(CommandPlan::CreateForeignTableDefinition(value)))
438            }
439            Statement::Merge(statement) => {
440                let mut subqueries = Vec::new();
441                let source = SourcePlan::lower_with(statement.source, aggregates, &mut subqueries);
442                let join_condition =
443                    lower_scalar_expression(statement.join_condition, aggregates, &mut subqueries);
444                let when_clauses = statement
445                    .when_clauses
446                    .into_iter()
447                    .map(|clause| lower_merge_when(clause, aggregates, &mut subqueries))
448                    .collect();
449                let returning = statement
450                    .returning
451                    .into_iter()
452                    .map(|projection| {
453                        ProjectionPlan::lower_with(projection, aggregates, &mut subqueries)
454                    })
455                    .collect();
456                Self::Command(Box::new(CommandPlan::Merge(Box::new(MergePlan {
457                    ctes: lower_ctes(&statement.with, aggregates),
458                    target: statement.target,
459                    statement_privilege_subject: None,
460                    target_privilege_subject: None,
461                    target_qualifier: statement.target_qualifier,
462                    target_alias: statement.target_alias,
463                    include_descendants: statement.include_descendants,
464                    target_predicate: None,
465                    source: Box::new(source),
466                    join_condition,
467                    when_clauses,
468                    returning,
469                    returning_aliases: statement.returning_aliases,
470                    subqueries,
471                    view_checks: Vec::new(),
472                }))))
473            }
474            Statement::CreateFunction(value) => {
475                Self::Command(Box::new(CommandPlan::CreateFunction(value)))
476            }
477            Statement::DropFunction(value) => {
478                Self::Command(Box::new(CommandPlan::DropFunction(value)))
479            }
480            Statement::AlterRoutine(value) => {
481                Self::Command(Box::new(CommandPlan::AlterRoutine(value)))
482            }
483            Statement::AlterRoutineOwner(value) => {
484                Self::Command(Box::new(CommandPlan::AlterRoutineOwner(value)))
485            }
486            Statement::RenameRoutine(value) => {
487                Self::Command(Box::new(CommandPlan::RenameRoutine(value)))
488            }
489            Statement::GrantRoutine(value) => {
490                Self::Command(Box::new(CommandPlan::GrantRoutine(value)))
491            }
492            Statement::GrantTable(value) => Self::Command(Box::new(CommandPlan::GrantTable(value))),
493            Statement::GrantSequence(value) => {
494                Self::Command(Box::new(CommandPlan::GrantSequence(value)))
495            }
496            Statement::GrantDatabase(value) => {
497                Self::Command(Box::new(CommandPlan::GrantDatabase(value)))
498            }
499            Statement::GrantSchema(value) => {
500                Self::Command(Box::new(CommandPlan::GrantSchema(value)))
501            }
502            Statement::GrantRole(value) => Self::Command(Box::new(CommandPlan::GrantRole(value))),
503            Statement::CreateRole(value) => Self::Command(Box::new(CommandPlan::CreateRole(value))),
504            Statement::AlterRole(value) => Self::Command(Box::new(CommandPlan::AlterRole(value))),
505            Statement::RenameRole(value) => Self::Command(Box::new(CommandPlan::RenameRole(value))),
506            Statement::DropRole(value) => Self::Command(Box::new(CommandPlan::DropRole(value))),
507            Statement::CreateTrigger(value) => {
508                Self::Command(Box::new(CommandPlan::CreateTrigger(value)))
509            }
510            Statement::DropTrigger(value) => {
511                Self::Command(Box::new(CommandPlan::DropTrigger(value)))
512            }
513            Statement::CreateRule(value) => Self::Command(Box::new(CommandPlan::CreateRule(value))),
514            Statement::DropRule(value) => Self::Command(Box::new(CommandPlan::DropRule(value))),
515            Statement::DoBlock { language, body } => {
516                Self::Command(Box::new(CommandPlan::DoBlock { language, body }))
517            }
518            Statement::Call { name, args } => Self::Command(Box::new(CommandPlan::Call {
519                name,
520                args: args
521                    .into_iter()
522                    .map(|expr| ExpressionPlan::lower_with(expr, aggregates))
523                    .collect(),
524            })),
525        }
526    }
527
528    #[must_use]
529    pub fn name(&self) -> &'static str {
530        match self {
531            Self::Query(_) => "Query",
532            Self::Command(command) => command.name(),
533        }
534    }
535
536    /// Rewrite every physical scalar slot owned by this plan, including
537    /// CTEs, scalar subqueries, mutation sources, prepared/explained bodies,
538    /// and routine-call arguments.  This is the plan-native binding hook used
539    /// by SQL-language routines; callers never need to reconstruct an AST to
540    /// specialize a stored plan.
541    pub fn rewrite_scalar_expressions(&mut self, rewrite: &mut dyn FnMut(&mut ScalarExpr)) {
542        match self {
543            Self::Query(query) => rewrite_query_scalars(query, rewrite),
544            Self::Command(command) => rewrite_command_scalars(command, rewrite),
545        }
546    }
547}
548
549impl CommandPlan {
550    #[must_use]
551    pub fn name(&self) -> &'static str {
552        match self {
553            Self::CreateTable(_) => "CreateTable",
554            Self::CreateTableIfNotExists(_) => "CreateTableIfNotExists",
555            Self::CreateIndex(_) => "CreateIndex",
556            Self::RenameIndex(_) => "RenameIndex",
557            Self::Insert(_) => "Insert",
558            Self::Update(_) => "Update",
559            Self::Delete(_) => "Delete",
560            Self::Drop(_) => "Drop",
561            Self::AlterTable(_) => "AlterTable",
562            Self::AlterView(_) => "AlterView",
563            Self::CreateView { .. } => "CreateView",
564            Self::CreateMaterializedView { .. } => "CreateMaterializedView",
565            Self::RefreshMaterializedView { .. } => "RefreshMaterializedView",
566            Self::CreateSchema { .. } => "CreateSchema",
567            Self::AlterSchemaOwner { .. } => "AlterSchemaOwner",
568            Self::RenameSchema { .. } => "RenameSchema",
569            Self::Notify { .. } => "Notify",
570            Self::Listen { .. } => "Listen",
571            Self::Unlisten { .. } => "Unlisten",
572            Self::SetVariable { .. } => "SetVariable",
573            Self::ResetVariable { .. } => "ResetVariable",
574            Self::ResetAllVariables => "ResetAllVariables",
575            Self::SetConstraints { .. } => "SetConstraints",
576            Self::ShowVariable { .. } => "ShowVariable",
577            Self::Discard { .. } => "Discard",
578            Self::Load { .. } => "Load",
579            Self::Explain { .. } => "Explain",
580            Self::Analyze { .. } => "Analyze",
581            Self::Vacuum(_) => "Vacuum",
582            Self::LockTable(_) => "LockTable",
583            Self::Truncate { .. } => "Truncate",
584            Self::Transaction(_) => "Transaction",
585            Self::DeclareCursor { .. } => "DeclareCursor",
586            Self::FetchCursor(_) => "FetchCursor",
587            Self::CloseCursor { .. } => "CloseCursor",
588            Self::CreateSequence(_) => "CreateSequence",
589            Self::CreateDomain(_) => "CreateDomain",
590            Self::AlterDomain(_) => "AlterDomain",
591            Self::CreateEnum(_) => "CreateEnum",
592            Self::CreateCompositeType(_) => "CreateCompositeType",
593            Self::AlterEnum(_) => "AlterEnum",
594            Self::AlterTypeObject(_) => "AlterTypeObject",
595            Self::GrantType(_) => "GrantType",
596            Self::AlterSequence(_) => "AlterSequence",
597            Self::CreateTableAs { .. } => "CreateTableAs",
598            Self::Prepare { .. } => "Prepare",
599            Self::Execute { .. } => "Execute",
600            Self::Deallocate { .. } => "Deallocate",
601            Self::CreateForeignWrapper(_) => "CreateForeignWrapper",
602            Self::CreateForeignServer(_) => "CreateForeignServer",
603            Self::CreateForeignTable(_) => "CreateForeignTable",
604            Self::CreateForeignTableDefinition(_) => "CreateForeignTableDefinition",
605            Self::AlterForeignTable(_) => "AlterForeignTable",
606            Self::Merge(_) => "Merge",
607            Self::CreateFunction(_) => "CreateFunction",
608            Self::DropFunction(_) => "DropFunction",
609            Self::AlterRoutine(_) => "AlterRoutine",
610            Self::AlterRoutineOwner(_) => "AlterRoutineOwner",
611            Self::RenameRoutine(_) => "RenameRoutine",
612            Self::GrantRoutine(_) => "GrantRoutine",
613            Self::GrantTable(_) => "GrantTable",
614            Self::GrantSequence(_) => "GrantSequence",
615            Self::GrantDatabase(_) => "GrantDatabase",
616            Self::GrantSchema(_) => "GrantSchema",
617            Self::GrantRole(_) => "GrantRole",
618            Self::CreateRole(_) => "CreateRole",
619            Self::AlterRole(_) => "AlterRole",
620            Self::RenameRole(_) => "RenameRole",
621            Self::DropRole(_) => "DropRole",
622            Self::CreateTrigger(_) => "CreateTrigger",
623            Self::DropTrigger(_) => "DropTrigger",
624            Self::CreateRule(_) => "CreateRule",
625            Self::DropRule(_) => "DropRule",
626            Self::DoBlock { .. } => "DoBlock",
627            Self::Call { .. } => "Call",
628        }
629    }
630}