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