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