1use crate::analysis::facts::{
3 AlterIndexActionFact, AlterTableActionFact, PersistenceFact, StatementFact, TypeCreationKind,
4};
5use crate::analysis::mutations::{
6 AlterDatabaseMutation, AlterDomainMutation, AlterFunctionMutation, AlterProcedureMutation,
7 AlterPublicationMutation, AlterRoleMutation, AlterSequenceMutation, AlterSubscriptionMutation,
8 AlterTable, AlterTableActionMutation, AlterTypeActionMutation, AlterTypeMutation,
9 ColumnMutation, CreateDatabaseMutation, CreateDomainMutation, CreateFunctionMutation,
10 CreateIndex, CreateMaterializedView, CreatePolicyMutation, CreateProcedureMutation,
11 CreatePublicationMutation, CreateRoleMutation, CreateSchemaMutation, CreateSequenceMutation,
12 CreateSubscriptionMutation, CreateTable, CreateTriggerMutation, CreateTypeMutation, CreateView,
13 DropDatabaseMutation, DropDomainMutation, DropFunctionMutation, DropIndex,
14 DropMaterializedViewMutation, DropPolicyMutation, DropProcedureMutation,
15 DropPublicationMutation, DropRoleMutation, DropSchemaMutation, DropSequenceMutation,
16 DropSubscriptionMutation, DropTable, DropTriggerMutation, DropTypeMutation, DropViewMutation,
17 FkMutation, GrantMutation, Mutation, OpaqueMutation, PersistenceMutation,
18 RefreshMaterializedViewMutation, ReleaseSavepointMutation, Rename, ResolvedGrantTarget,
19 RevokeMutation, RollbackToSavepointMutation, SavepointMutation, SearchPathChange,
20};
21use crate::analysis::state::AnalysisState;
22use crate::ast::identifiers::{ObjectId, QualifiedName};
23use crate::model::types::TypeKind;
24
25pub struct Resolver;
26
27impl Resolver {
28 fn resolve_creation_name(name: &QualifiedName, state: &AnalysisState) -> ObjectId {
29 let schema = name
30 .schema
31 .as_ref()
32 .map(|i| i.resolve())
33 .unwrap_or_else(|| {
34 state
35 .local
36 .search_path
37 .first()
38 .map(|s| s.as_str())
39 .unwrap_or("public")
40 .to_string()
41 });
42
43 ObjectId::new(schema, name.name.resolve())
44 }
45
46 fn resolve_lookup_name(name: &QualifiedName, state: &AnalysisState) -> ObjectId {
47 if let Some(schema_ident) = &name.schema {
48 return ObjectId::new(schema_ident.resolve(), name.name.resolve());
49 }
50
51 let resolved_name = name.name.resolve();
52
53 for schema in &state.local.search_path {
54 let mut candidate = ObjectId::new(schema.clone(), resolved_name.clone());
55 if state.local.relations.contains_key(&candidate)
56 || state.local.types.contains_key(&candidate)
57 || state.local.sequences.contains_key(&candidate)
58 || state.local.functions.keys().any(|k| {
59 k.schema == candidate.schema
60 && (k.name == candidate.name
61 || k.name.starts_with(&format!("{}(", candidate.name)))
62 })
63 {
64 candidate.inferred_schema = true;
65 return candidate;
66 }
67 }
68
69 let schema = state
70 .local
71 .search_path
72 .first()
73 .map(|s| s.as_str())
74 .unwrap_or("public")
75 .to_string();
76 let mut id = ObjectId::new(schema, resolved_name);
77 id.inferred_schema = true;
78 id
79 }
80
81 fn resolve_function_id(
82 name: &QualifiedName,
83 params: &[crate::analysis::facts::ParamFact],
84 state: &AnalysisState,
85 ) -> ObjectId {
86 let base_id = Self::resolve_creation_name(name, state);
87 let sig = params
88 .iter()
89 .map(|p| p.ty.clone())
90 .collect::<Vec<_>>()
91 .join(",");
92 Self::resolve_function_id_by_sig(&base_id, &sig)
93 }
94
95 fn resolve_function_id_by_sig(base_id: &ObjectId, sig: &str) -> ObjectId {
96 let normalized_sig = sig
98 .split(',')
99 .map(Self::normalize_function_arg_type)
100 .collect::<Vec<_>>()
101 .join(",");
102
103 let mut id = ObjectId::new(
104 base_id.schema.clone(),
105 format!("{}({})", base_id.name, normalized_sig),
106 );
107 id.inferred_schema = base_id.inferred_schema;
108 id
109 }
110
111 fn normalize_function_arg_type(raw: &str) -> String {
112 let normalized = raw.trim().to_lowercase();
113 if let Some(element_type) = normalized.strip_suffix("[]") {
114 return format!("{}[]", Self::normalize_function_arg_type(element_type));
115 }
116 match normalized.as_str() {
117 "int" | "int4" => "integer".to_string(),
118 "int8" => "bigint".to_string(),
119 "int2" => "smallint".to_string(),
120 "float8" => "double precision".to_string(),
121 "float4" => "real".to_string(),
122 "bool" => "boolean".to_string(),
123 "varchar" => "character varying".to_string(),
124 "char" => "character".to_string(),
125 "time" => "time without time zone".to_string(),
126 "timestamp" => "timestamp without time zone".to_string(),
127 "timestamptz" => "timestamp with time zone".to_string(),
128 "decimal" => "numeric".to_string(),
129 _ => normalized,
130 }
131 }
132
133 fn resolve_grant_target(
134 target: &crate::analysis::facts::GrantTarget,
135 state: &AnalysisState,
136 ) -> ResolvedGrantTarget {
137 match target {
138 crate::analysis::facts::GrantTarget::Tables(names) => ResolvedGrantTarget::Tables(
139 names
140 .iter()
141 .map(|n| Self::resolve_lookup_name(n, state))
142 .collect(),
143 ),
144 crate::analysis::facts::GrantTarget::AllTablesInSchema(schemas) => {
145 ResolvedGrantTarget::AllTablesInSchema(schemas.clone())
146 }
147 }
148 }
149
150 pub fn resolve(fact: &StatementFact, state: &AnalysisState) -> Vec<Mutation> {
151 let mut mutations = Vec::new();
152 match fact {
153 StatementFact::CreateSchema {
154 name,
155 if_not_exists,
156 } => {
157 mutations.push(Mutation::CreateSchema(CreateSchemaMutation {
158 name: name.name.resolve(),
159 if_not_exists: *if_not_exists,
160 }));
161 }
162 StatementFact::AlterSchema { name, new_name } => {
163 if let Some(nn) = new_name {
164 let id = Self::resolve_lookup_name(name, state);
165 let mut new_id = ObjectId::new(id.schema.clone(), nn.resolve());
166 new_id.inferred_schema = id.inferred_schema;
167 mutations.push(Mutation::Rename(Rename { old_id: id, new_id }));
168 }
169 }
170 StatementFact::DropSchema {
171 names,
172 if_exists,
173 cascade,
174 } => {
175 mutations.push(Mutation::DropSchema(DropSchemaMutation {
176 names: names.iter().map(|n| n.name.resolve()).collect(),
177 if_exists: *if_exists,
178 cascade: *cascade,
179 }));
180 }
181 StatementFact::CreateTable {
182 name,
183 if_not_exists,
184 as_select,
185 persistence,
186 columns,
187 foreign_keys,
188 table_constraints,
189 partition_by,
190 partition_of,
191 partition_type,
192 } => {
193 let id = Self::resolve_creation_name(name, state);
194
195 let resolved_persistence = match persistence {
196 PersistenceFact::Permanent => PersistenceMutation::Permanent,
197 PersistenceFact::Temporary => PersistenceMutation::Temporary,
198 PersistenceFact::Unlogged => PersistenceMutation::Unlogged,
199 };
200
201 let col_mutations: Vec<ColumnMutation> = columns
202 .iter()
203 .map(|c| ColumnMutation {
204 name: c.name.clone(),
205 ty: c.ty.clone(),
206 not_null: c.not_null,
207 is_primary_key: c.is_primary_key,
208 default: c.default.clone(),
209 })
210 .collect();
211
212 let mut fk_mutations = Vec::new();
213 for fk in foreign_keys {
214 let to_table = Self::resolve_lookup_name(&fk.references, state);
215
216 fk_mutations.push(FkMutation {
217 constraint_name: fk.constraint_name.clone(),
218 to_table,
219 from_columns: fk.from_columns.clone(),
220 to_columns: fk.to_columns.clone(),
221 });
222 }
223
224 let partition_of_id = partition_of
225 .as_ref()
226 .map(|n| Self::resolve_lookup_name(n, state));
227
228 mutations.push(Mutation::CreateTable(CreateTable {
229 id,
230 if_not_exists: *if_not_exists,
231 as_select: *as_select,
232 persistence: resolved_persistence,
233 columns: col_mutations,
234 foreign_keys: fk_mutations,
235 table_constraints: table_constraints.clone(),
236 partition_by: partition_by.clone(),
237 partition_of: partition_of_id,
238 partition_type: partition_type.clone(),
239 }));
240 }
241 StatementFact::CreateView {
242 name,
243 or_replace,
244 depends_on,
245 } => {
246 let id = Self::resolve_creation_name(name, state);
247
248 let resolved_depends = depends_on
249 .iter()
250 .map(|n| Self::resolve_lookup_name(n, state))
251 .collect();
252
253 mutations.push(Mutation::CreateView(CreateView {
254 id,
255 or_replace: *or_replace,
256 depends_on: resolved_depends,
257 }));
258 }
259 StatementFact::AlterView { name, action } => {
260 match action {
261 crate::analysis::facts::AlterViewAction::RenameTo { new_name } => {
262 let id = Self::resolve_lookup_name(name, state);
263 let mut new_id = ObjectId::new(id.schema.clone(), new_name.resolve());
264 new_id.inferred_schema = id.inferred_schema;
265 mutations.push(Mutation::Rename(Rename { old_id: id, new_id }));
266 }
267 crate::analysis::facts::AlterViewAction::SetSchema { .. } => {
268 }
271 crate::analysis::facts::AlterViewAction::OwnerTo { .. }
272 | crate::analysis::facts::AlterViewAction::SetDefault { .. }
273 | crate::analysis::facts::AlterViewAction::DropDefault { .. }
274 | crate::analysis::facts::AlterViewAction::RenameColumn { .. }
275 | crate::analysis::facts::AlterViewAction::SetOptions { .. }
276 | crate::analysis::facts::AlterViewAction::ResetOptions { .. } => {
277 }
281 }
282 }
283 StatementFact::CreateMaterializedView { name, depends_on } => {
284 let id = Self::resolve_creation_name(name, state);
285
286 let resolved_depends = depends_on
287 .iter()
288 .map(|n| Self::resolve_lookup_name(n, state))
289 .collect();
290
291 mutations.push(Mutation::CreateMaterializedView(CreateMaterializedView {
292 id,
293 depends_on: resolved_depends,
294 }));
295 }
296 StatementFact::AlterMaterializedView { name, new_name } => {
297 if let Some(new_name) = new_name {
298 let id = Self::resolve_lookup_name(name, state);
299 let mut new_id = ObjectId::new(id.schema.clone(), new_name.resolve());
300 new_id.inferred_schema = id.inferred_schema;
301 mutations.push(Mutation::Rename(Rename { old_id: id, new_id }));
302 }
303 }
304 StatementFact::RefreshMaterializedView { name, concurrently } => {
305 mutations.push(Mutation::RefreshMaterializedView(
306 RefreshMaterializedViewMutation {
307 id: Self::resolve_lookup_name(name, state),
308 concurrently: *concurrently,
309 },
310 ));
311 }
312 StatementFact::CreateIndex {
313 name,
314 relation,
315 if_not_exists,
316 concurrently,
317 using_method,
318 has_predicate,
319 unique,
320 } => {
321 let table = Self::resolve_lookup_name(relation, state);
322 let id = if name.schema.is_some() {
325 Self::resolve_creation_name(name, state)
326 } else {
327 ObjectId::new(table.schema.clone(), name.name.resolve())
328 };
329
330 mutations.push(Mutation::CreateIndex(CreateIndex {
331 id,
332 table,
333 if_not_exists: *if_not_exists,
334 concurrently: *concurrently,
335 using_method: using_method.clone(),
336 has_predicate: *has_predicate,
337 unique: *unique,
338 }));
339 }
340 StatementFact::CreatePolicy {
341 name,
342 table,
343 permissive,
344 command,
345 } => {
346 mutations.push(Mutation::CreatePolicy(CreatePolicyMutation {
347 name: name.clone(),
348 table: Self::resolve_lookup_name(table, state),
349 permissive: *permissive,
350 command: command.clone(),
351 }));
352 }
353 StatementFact::DropPolicy {
354 name,
355 table,
356 if_exists,
357 } => {
358 mutations.push(Mutation::DropPolicy(DropPolicyMutation {
359 name: name.clone(),
360 table: Self::resolve_lookup_name(table, state),
361 if_exists: *if_exists,
362 }));
363 }
364 StatementFact::CreateTrigger {
365 name,
366 table,
367 function,
368 } => {
369 let function_base = function
373 .as_ref()
374 .map(|f| Self::resolve_lookup_name(f, state))
375 .unwrap_or_else(|| ObjectId::new("public", "unknown_function"));
376 let function_id = Self::resolve_function_id_by_sig(&function_base, "");
377 mutations.push(Mutation::CreateTrigger(CreateTriggerMutation {
378 name: name.clone(),
379 table: Self::resolve_lookup_name(table, state),
380 function_id,
381 }));
382 }
383 StatementFact::DropTrigger {
384 name,
385 table,
386 if_exists,
387 } => {
388 mutations.push(Mutation::DropTrigger(DropTriggerMutation {
389 name: name.clone(),
390 table: Self::resolve_lookup_name(table, state),
391 if_exists: *if_exists,
392 }));
393 }
394 StatementFact::AlterIndex { name, actions } => {
395 let id = Self::resolve_lookup_name(name, state);
396 for action in actions {
397 match action {
398 AlterIndexActionFact::RenameTo { new_name } => {
399 let mut new_id = ObjectId::new(id.schema.clone(), new_name.resolve());
400 new_id.inferred_schema = id.inferred_schema;
401 mutations.push(Mutation::Rename(Rename {
402 old_id: id.clone(),
403 new_id,
404 }));
405 }
406 }
407 }
408 }
409 StatementFact::CreateType(create_type) => {
410 let id = Self::resolve_creation_name(&create_type.name, state);
411
412 let mapped_kind = match create_type.kind {
413 TypeCreationKind::Enum => TypeKind::Enum { variants: vec![] },
414 TypeCreationKind::Range => TypeKind::Range,
415 TypeCreationKind::Composite => TypeKind::Composite,
416 TypeCreationKind::Base => TypeKind::Base,
417 };
418
419 mutations.push(Mutation::CreateType(CreateTypeMutation {
420 id,
421 kind: mapped_kind,
422 }));
423 }
424 StatementFact::AlterType(alter_type) => {
425 let id = Self::resolve_lookup_name(&alter_type.name, state);
426 for action_fact in &alter_type.actions {
427 match action_fact {
428 crate::analysis::facts::AlterTypeActionFact::AddValue {
429 new_value,
430 neighbor,
431 before,
432 } => {
433 mutations.push(Mutation::AlterType(AlterTypeMutation {
434 id: id.clone(),
435 action: AlterTypeActionMutation::AddValue {
436 new_value: new_value.clone(),
437 neighbor: neighbor.clone(),
438 before: *before,
439 },
440 }));
441 }
442 }
443 }
444 }
445 StatementFact::CreateDomain { name, base_type } => {
446 let id = Self::resolve_creation_name(name, state);
447
448 mutations.push(Mutation::CreateDomain(CreateDomainMutation {
449 id,
450 base_type: base_type.clone(),
451 }));
452 }
453 StatementFact::AlterDomain { name, action } => {
454 mutations.push(Mutation::AlterDomain(AlterDomainMutation {
455 id: Self::resolve_lookup_name(name, state),
456 action: action.clone(),
457 }));
458 }
459 StatementFact::DropDomain {
460 names,
461 if_exists,
462 cascade,
463 } => {
464 let ids = names
465 .iter()
466 .map(|n| Self::resolve_lookup_name(n, state))
467 .collect();
468 mutations.push(Mutation::DropDomain(DropDomainMutation {
469 ids,
470 if_exists: *if_exists,
471 cascade: *cascade,
472 }));
473 }
474 StatementFact::DropType {
475 names,
476 if_exists,
477 cascade,
478 } => {
479 let ids = names
480 .iter()
481 .map(|n| Self::resolve_lookup_name(n, state))
482 .collect();
483 mutations.push(Mutation::DropType(DropTypeMutation {
484 ids,
485 if_exists: *if_exists,
486 cascade: *cascade,
487 }));
488 }
489 StatementFact::CreateSequence {
490 name,
491 if_not_exists,
492 owned_by,
493 } => {
494 let id = Self::resolve_creation_name(name, state);
495
496 let resolved_owned_by = owned_by.as_ref().map(|(table_name, col)| {
497 (Self::resolve_lookup_name(table_name, state), col.clone())
498 });
499 mutations.push(Mutation::CreateSequence(CreateSequenceMutation {
500 id,
501 if_not_exists: *if_not_exists,
502 owned_by: resolved_owned_by,
503 }));
504 }
505 StatementFact::AlterSequence { name, owned_by } => {
506 let resolved_owned_by = owned_by.as_ref().map(|(table_name, col)| {
507 (Self::resolve_lookup_name(table_name, state), col.clone())
508 });
509 mutations.push(Mutation::AlterSequence(AlterSequenceMutation {
510 id: Self::resolve_lookup_name(name, state),
511 owned_by: resolved_owned_by,
512 }));
513 }
514 StatementFact::DropSequence {
515 names,
516 if_exists,
517 cascade,
518 } => {
519 let ids = names
520 .iter()
521 .map(|n| Self::resolve_lookup_name(n, state))
522 .collect();
523 mutations.push(Mutation::DropSequence(DropSequenceMutation {
524 ids,
525 if_exists: *if_exists,
526 cascade: *cascade,
527 }));
528 }
529 StatementFact::AlterTable { name, actions } => {
530 let id = Self::resolve_lookup_name(name, state);
531 for action_fact in actions {
532 let action = match action_fact {
533 AlterTableActionFact::AddColumn {
534 name: col_name,
535 ty,
536 if_not_exists,
537 not_null,
538 default,
539 } => AlterTableActionMutation::AddColumn {
540 name: col_name.clone(),
541 ty: ty.clone(),
542 if_not_exists: *if_not_exists,
543 not_null: *not_null,
544 default: default.clone(),
545 depends_on: None, },
547 AlterTableActionFact::DropColumn {
548 name: col_name,
549 if_exists,
550 } => AlterTableActionMutation::DropColumn {
551 name: col_name.clone(),
552 if_exists: *if_exists,
553 },
554 AlterTableActionFact::RenameColumn { from, to } => {
555 AlterTableActionMutation::RenameColumn {
556 from: from.resolve(),
557 to: to.resolve(),
558 }
559 }
560 AlterTableActionFact::RenameTo { new_name } => {
561 let mut new_id = ObjectId::new(id.schema.clone(), new_name.resolve());
562 new_id.inferred_schema = id.inferred_schema;
563 mutations.push(Mutation::Rename(Rename {
564 old_id: id.clone(),
565 new_id,
566 }));
567 continue;
568 }
569 AlterTableActionFact::AddForeignKey {
570 constraint_name,
571 references,
572 from_columns,
573 to_columns,
574 not_valid,
575 } => {
576 let to_table = Self::resolve_lookup_name(references, state);
577 if !state.relation_is_present(&to_table) {
578 return vec![Mutation::Opaque(
579 OpaqueMutation::UnresolvedReference {
580 object_kind: crate::report::violations::ObjectKind::Table,
581 object_name: to_table.to_string(),
582 },
583 )];
584 }
585 AlterTableActionMutation::AddForeignKey {
586 constraint_name: constraint_name.clone(),
587 to_table,
588 from_columns: from_columns.clone(),
589 to_columns: to_columns.clone(),
590 not_valid: *not_valid,
591 }
592 }
593 AlterTableActionFact::AlterConstraint {
594 name: c_name,
595 deferrable,
596 } => AlterTableActionMutation::AlterConstraint {
597 name: c_name.clone(),
598 deferrable: *deferrable,
599 },
600 AlterTableActionFact::RenameConstraint { old_name, new_name } => {
601 AlterTableActionMutation::RenameConstraint {
602 old_name: old_name.clone(),
603 new_name: new_name.clone(),
604 }
605 }
606 AlterTableActionFact::DropConstraint { name: c_name } => {
607 AlterTableActionMutation::DropConstraint {
608 name: c_name.clone(),
609 }
610 }
611 AlterTableActionFact::AddCheckConstraint {
612 constraint_name,
613 not_valid,
614 } => AlterTableActionMutation::AddCheckConstraint {
615 constraint_name: constraint_name.clone(),
616 not_valid: *not_valid,
617 },
618 AlterTableActionFact::AddUniqueConstraint { constraint_name } => {
619 AlterTableActionMutation::AddUniqueConstraint {
620 constraint_name: constraint_name.clone(),
621 }
622 }
623 AlterTableActionFact::AddPrimaryKeyConstraint => {
624 AlterTableActionMutation::AddPrimaryKeyConstraint
625 }
626 AlterTableActionFact::AddExcludeConstraint => {
627 AlterTableActionMutation::AddExcludeConstraint
628 }
629 AlterTableActionFact::SetNotNull { column } => {
630 AlterTableActionMutation::SetNotNull {
631 column: column.clone(),
632 }
633 }
634 AlterTableActionFact::DropNotNull { column } => {
635 AlterTableActionMutation::DropNotNull {
636 column: column.clone(),
637 }
638 }
639 AlterTableActionFact::SetType {
640 column,
641 ty,
642 has_using,
643 } => AlterTableActionMutation::SetType {
644 column: column.clone(),
645 ty: ty.clone(),
646 has_using: *has_using,
647 },
648 AlterTableActionFact::SetDefault { column, default } => {
649 AlterTableActionMutation::SetDefault {
650 column: column.clone(),
651 default: default.clone(),
652 }
653 }
654 AlterTableActionFact::ValidateConstraint { constraint_name } => {
655 AlterTableActionMutation::ValidateConstraint {
656 constraint_name: constraint_name.clone(),
657 }
658 }
659 AlterTableActionFact::AttachPartition { child } => {
660 let child_id = Self::resolve_lookup_name(child, state);
661
662 AlterTableActionMutation::AttachPartition { child: child_id }
663 }
664 AlterTableActionFact::DetachPartition { child } => {
665 AlterTableActionMutation::DetachPartition {
666 child: Self::resolve_lookup_name(child, state),
667 }
668 }
669 AlterTableActionFact::SetStorage { column } => {
670 AlterTableActionMutation::SetStorage {
671 column: column.clone(),
672 }
673 }
674 AlterTableActionFact::SetAccessMethod => {
675 AlterTableActionMutation::SetAccessMethod
676 }
677 AlterTableActionFact::DisableTrigger { trigger_name } => {
678 AlterTableActionMutation::DisableTrigger {
679 trigger_name: trigger_name.clone(),
680 }
681 }
682 AlterTableActionFact::EnableTrigger { trigger_name } => {
683 AlterTableActionMutation::EnableTrigger {
684 trigger_name: trigger_name.clone(),
685 }
686 }
687 AlterTableActionFact::SetExpression { .. }
688 | AlterTableActionFact::SetOptions { .. }
689 | AlterTableActionFact::Inherit { .. }
690 | AlterTableActionFact::NoInherit { .. }
691 | AlterTableActionFact::ClusterOn { .. }
692 | AlterTableActionFact::InheritTable { .. }
693 | AlterTableActionFact::NoInheritTable { .. }
694 | AlterTableActionFact::MergePartitions { .. }
695 | AlterTableActionFact::SplitPartition
696 | AlterTableActionFact::SetSchema { .. }
697 | AlterTableActionFact::SetTablespace { .. }
698 | AlterTableActionFact::SetLogged
699 | AlterTableActionFact::SetUnlogged
700 | AlterTableActionFact::OwnerTo { .. }
701 | AlterTableActionFact::ReplicaIdentity { .. }
702 | AlterTableActionFact::ForceRls
703 | AlterTableActionFact::EnableRls
704 | AlterTableActionFact::DisableRls
705 | AlterTableActionFact::EnableAlwaysTrigger { .. }
706 | AlterTableActionFact::EnableReplicaTrigger { .. } => {
707 AlterTableActionMutation::Opaque
708 }
709 };
710 mutations.push(Mutation::AlterTable(AlterTable {
711 id: id.clone(),
712 action,
713 }));
714 }
715 }
716 StatementFact::DropTable {
717 name,
718 if_exists,
719 cascade,
720 } => {
721 let id = Self::resolve_lookup_name(name, state);
722
723 mutations.push(Mutation::DropTable(DropTable {
727 id,
728 if_exists: *if_exists,
729 cascade: *cascade,
730 }));
731 }
732 StatementFact::DropView {
733 name,
734 if_exists,
735 cascade,
736 } => {
737 mutations.push(Mutation::DropView(DropViewMutation {
738 ids: vec![Self::resolve_lookup_name(name, state)],
739 if_exists: *if_exists,
740 cascade: *cascade,
741 }));
742 }
743 StatementFact::DropMaterializedView {
744 names,
745 if_exists,
746 cascade,
747 } => {
748 let ids = names
749 .iter()
750 .map(|n| Self::resolve_lookup_name(n, state))
751 .collect();
752 mutations.push(Mutation::DropMaterializedView(
753 DropMaterializedViewMutation {
754 ids,
755 if_exists: *if_exists,
756 cascade: *cascade,
757 },
758 ));
759 }
760 StatementFact::DropIndex {
761 names,
762 if_exists,
763 concurrently,
764 } => {
765 for name in names {
766 mutations.push(Mutation::DropIndex(DropIndex {
767 id: Self::resolve_lookup_name(name, state),
768 if_exists: *if_exists,
769 concurrently: *concurrently,
770 }));
771 }
772 }
773 StatementFact::SetSearchPath { target } => {
774 mutations.push(Mutation::SearchPath(SearchPathChange {
775 target: target.clone(),
776 }))
777 }
778 StatementFact::BeginTransaction => mutations.push(Mutation::BeginTransaction),
779 StatementFact::CommitTransaction => mutations.push(Mutation::CommitTransaction),
780 StatementFact::RollbackTransaction => mutations.push(Mutation::RollbackTransaction),
781 StatementFact::RollbackToSavepoint { name } => {
782 mutations.push(Mutation::RollbackToSavepoint(RollbackToSavepointMutation {
783 name: name.clone(),
784 }))
785 }
786 StatementFact::Savepoint { name } => {
787 mutations.push(Mutation::Savepoint(SavepointMutation {
788 name: name.clone(),
789 }))
790 }
791 StatementFact::ReleaseSavepoint { name } => {
792 mutations.push(Mutation::ReleaseSavepoint(ReleaseSavepointMutation {
793 name: name.clone(),
794 }))
795 }
796 StatementFact::PrepareTransaction { .. } => {
797 mutations.push(Mutation::Opaque(OpaqueMutation::PrepareTransaction))
798 }
799 StatementFact::SetTransaction => {
800 mutations.push(Mutation::Opaque(OpaqueMutation::SetTransaction))
801 }
802 StatementFact::SetConstraints => {
803 mutations.push(Mutation::Opaque(OpaqueMutation::SetConstraints))
804 }
805 StatementFact::OpaqueBlock => mutations.push(Mutation::Opaque(OpaqueMutation::DoBlock)),
806 StatementFact::Execute => mutations.push(Mutation::Opaque(OpaqueMutation::Execute)),
807 StatementFact::Vacuum { relation, is_full } => {
808 let table_id = relation
809 .as_ref()
810 .map(|r| Self::resolve_lookup_name(r, state));
811 mutations.push(Mutation::Vacuum {
812 table_id,
813 is_full: *is_full,
814 })
815 }
816 StatementFact::CreateFunction(f) => {
817 let id = Self::resolve_function_id(&f.name, &f.params, state);
818 mutations.push(Mutation::CreateFunction(CreateFunctionMutation {
819 id,
820 or_replace: f.or_replace,
821 params: f.params.clone(),
822 return_type: f.return_type.clone(),
823 options: f.options.clone(),
824 }));
825 }
826 StatementFact::AlterFunction(f) => {
827 let base_id = Self::resolve_lookup_name(&f.name, state);
828 let sig = f.params.join(",");
829 let id = Self::resolve_function_id_by_sig(&base_id, &sig);
830 mutations.push(Mutation::AlterFunction(AlterFunctionMutation {
831 id,
832 action: f.action.clone(),
833 }));
834 }
835 StatementFact::DropFunction(f) => {
836 let mut signatures = Vec::new();
837 for sig in &f.signatures {
838 let mut normalized_sig = sig.clone();
839 normalized_sig.params = normalized_sig
840 .params
841 .into_iter()
842 .map(|p| Self::normalize_function_arg_type(&p))
843 .collect();
844 signatures.push(normalized_sig);
845 }
846 mutations.push(Mutation::DropFunction(DropFunctionMutation {
847 signatures,
848 if_exists: f.if_exists,
849 cascade: f.cascade,
850 }));
851 }
852 StatementFact::CreateProcedure(p) => {
853 let id = Self::resolve_function_id(&p.name, &p.params, state);
854 mutations.push(Mutation::CreateProcedure(CreateProcedureMutation {
855 id,
856 or_replace: p.or_replace,
857 params: p.params.clone(),
858 options: p.options.clone(),
859 }));
860 }
861 StatementFact::AlterProcedure(p) => {
862 let base_id = Self::resolve_lookup_name(&p.name, state);
863 let sig = p
864 .params
865 .iter()
866 .map(|p| p.to_string())
867 .collect::<Vec<_>>()
868 .join(",");
869 let id = Self::resolve_function_id_by_sig(&base_id, &sig);
870 mutations.push(Mutation::AlterProcedure(AlterProcedureMutation {
871 id,
872 action: p.action.clone(),
873 }));
874 }
875 StatementFact::DropProcedure(p) => {
876 mutations.push(Mutation::DropProcedure(DropProcedureMutation {
877 signatures: p.signatures.clone(),
878 if_exists: p.if_exists,
879 cascade: p.cascade,
880 }));
881 }
882 StatementFact::CreatePublication(p) => {
883 mutations.push(Mutation::CreatePublication(CreatePublicationMutation {
884 name: p.name.clone(),
885 scope: p.scope.clone(),
886 params: p.params.clone(),
887 }));
888 }
889 StatementFact::AlterPublication(p) => {
890 mutations.push(Mutation::AlterPublication(AlterPublicationMutation {
891 name: p.name.clone(),
892 }));
893 }
894 StatementFact::DropPublication(p) => {
895 mutations.push(Mutation::DropPublication(DropPublicationMutation {
896 names: p.names.clone(),
897 if_exists: p.if_exists,
898 cascade: p.cascade,
899 }));
900 }
901 StatementFact::CreateSubscription(s) => {
902 mutations.push(Mutation::CreateSubscription(CreateSubscriptionMutation {
903 name: s.name.clone(),
904 connection: s.connection.clone(),
905 publications: s.publications.clone(),
906 params: s.params.clone(),
907 }));
908 }
909 StatementFact::AlterSubscription(s) => {
910 mutations.push(Mutation::AlterSubscription(AlterSubscriptionMutation {
911 name: s.name.clone(),
912 }));
913 }
914 StatementFact::DropSubscription(s) => {
915 mutations.push(Mutation::DropSubscription(DropSubscriptionMutation {
916 name: s.name.clone(),
917 if_exists: s.if_exists,
918 }));
919 }
920 StatementFact::CreateRole(r) => {
921 mutations.push(Mutation::CreateRole(CreateRoleMutation {
922 name: r.name.clone(),
923 inherits: r.inherits,
924 }));
925 }
926 StatementFact::AlterRole(r) => {
927 mutations.push(Mutation::AlterRole(AlterRoleMutation {
928 name: r.name.clone(),
929 inherits: r.inherits,
930 }));
931 }
932 StatementFact::DropRole(r) => {
933 mutations.push(Mutation::DropRole(DropRoleMutation {
934 names: r.names.clone(),
935 if_exists: r.if_exists,
936 }));
937 }
938 StatementFact::Grant(g) => {
939 mutations.push(Mutation::Grant(GrantMutation {
940 privileges: g.privileges.clone(),
941 target: Self::resolve_grant_target(&g.target, state),
942 grantees: g.grantees.clone(),
943 with_grant_option: g.with_grant_option,
944 granted_by: g.granted_by.clone(),
945 }));
946 }
947 StatementFact::Revoke(r) => {
948 mutations.push(Mutation::Revoke(RevokeMutation {
949 grant_option_only: r.grant_option_only,
950 privileges: r.privileges.clone(),
951 target: Self::resolve_grant_target(&r.target, state),
952 revokees: r.revokees.clone(),
953 granted_by: r.granted_by.clone(),
954 cascade: r.cascade,
955 }));
956 }
957 StatementFact::CreateDatabase(d) => {
958 mutations.push(Mutation::CreateDatabase(CreateDatabaseMutation {
959 name: d.name.clone(),
960 options: d.options.clone(),
961 }));
962 }
963 StatementFact::AlterDatabase(d) => {
964 let id = Self::resolve_lookup_name(&d.name, state);
965 mutations.push(Mutation::AlterDatabase(AlterDatabaseMutation {
966 id,
967 action: d.action.clone(),
968 }));
969 }
970 StatementFact::DropDatabase(d) => {
971 let id = Self::resolve_lookup_name(&d.name, state);
972 mutations.push(Mutation::DropDatabase(DropDatabaseMutation {
973 id,
974 if_exists: d.if_exists,
975 }));
976 }
977 }
978 mutations
979 }
980}