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