uqa_sql/schema/table_alteration/
targets.rs1use super::syntax::{
9 alter_foreign_table_from_table_syntax, alter_sequence_from_table_syntax,
10 alter_view_from_table_syntax,
11};
12use crate::{
13 ast::{AlterForeignTableStmt, AlterSequence, AlterTableAction, AlterTableStmt, AlterViewStmt},
14 catalog::resolution::RelationResolution,
15 schema::relation_alteration::RelationAlterTarget,
16 SQLError,
17};
18
19pub enum BoundTableAlteration {
20 Table(AlterTableStmt),
21 Sequence(AlterSequence),
22 View(AlterViewStmt),
23 ForeignTable(AlterForeignTableStmt),
24 IndexRename {
25 name: String,
26 new_name: String,
27 },
28 ViewEvents {
29 name: String,
30 actions: Vec<AlterTableAction>,
31 },
32 ForeignTableEvents {
33 name: String,
34 actions: Vec<AlterTableAction>,
35 },
36}
37
38pub fn table_alter_target(
39 resolution: RelationResolution,
40 statement: &AlterTableStmt,
41 notice: &mut dyn FnMut(&str),
42) -> Result<Option<RelationAlterTarget>, SQLError> {
43 RelationAlterTarget::resolve(resolution, &statement.table, statement.if_exists, notice)
44}
45
46pub fn bind_table_alteration(
47 target: RelationAlterTarget,
48 mut statement: AlterTableStmt,
49) -> Result<BoundTableAlteration, SQLError> {
50 let RelationAlterTarget {
51 canonical,
52 relation,
53 kind,
54 } = target;
55 let bound = match kind {
56 "index"
57 if matches!(
58 statement.actions.as_slice(),
59 [AlterTableAction::RenameTable { .. }]
60 ) =>
61 {
62 let AlterTableAction::RenameTable { to } = &statement.actions[0] else {
63 unreachable!();
64 };
65 BoundTableAlteration::IndexRename {
66 name: canonical,
67 new_name: to.clone(),
68 }
69 }
70 "table" => {
71 statement.table = canonical;
72 BoundTableAlteration::Table(statement)
73 }
74 "sequence" => BoundTableAlteration::Sequence(alter_sequence_from_table_syntax(
75 &canonical, &statement,
76 )?),
77 "foreign table" => match alter_foreign_table_from_table_syntax(&canonical, &statement)? {
78 Some(change) => BoundTableAlteration::ForeignTable(change),
79 None => BoundTableAlteration::ForeignTableEvents {
80 name: canonical,
81 actions: statement.actions,
82 },
83 },
84 "view" | "materialized view" => {
85 match alter_view_from_table_syntax(&canonical, &relation.name, kind, &statement)? {
86 Some(change) => BoundTableAlteration::View(change),
87 None => BoundTableAlteration::ViewEvents {
88 name: canonical,
89 actions: statement.actions,
90 },
91 }
92 }
93 "composite type" => {
95 let local = uqa_core::RelationIdentity::from_legacy_name(&canonical)
96 .map_or_else(|_| canonical.clone(), |relation| relation.name);
97 return Err(SQLError::Diagnostic {
98 sqlstate: "42809".into(),
99 message: format!("\"{local}\" is a composite type"),
100 detail: None,
101 hint: Some("Use ALTER TYPE instead.".into()),
102 });
103 }
104 _ => {
105 return Err(SQLError::Routine {
106 sqlstate: "42809".into(),
107 message: format!("ALTER TABLE: relation `{canonical}` is a {kind}, not a table"),
108 });
109 }
110 };
111 Ok(bound)
112}
113
114#[cfg(test)]
115mod tests;