toasty_sql/stmt/
alter_column.rs

1use crate::stmt::ColumnDef;
2
3use super::Statement;
4
5use toasty_core::{
6    driver::Capability,
7    schema::db::{Column, ColumnId, Type},
8};
9
10/// A statement to alter a column in a table.
11#[derive(Debug, Clone)]
12pub struct AlterColumn {
13    /// ID of the column being altered.
14    pub id: ColumnId,
15
16    /// Current column definition.
17    pub column_def: ColumnDef,
18
19    /// Changes to be made to the column.
20    pub changes: AlterColumnChanges,
21}
22
23/// A statement to alter a column in a table.
24#[derive(Debug, Clone)]
25pub struct AlterColumnChanges {
26    /// New name for the column (if renaming).
27    pub new_name: Option<String>,
28
29    /// New type information.
30    pub new_ty: Option<Type>,
31
32    /// New nullability constraint.
33    pub new_not_null: Option<bool>,
34
35    /// New auto increment behavior.
36    pub new_auto_increment: Option<bool>,
37}
38
39impl AlterColumnChanges {
40    pub fn from_diff(previous: &Column, next: &Column) -> Self {
41        Self {
42            new_name: (previous.name != next.name).then(|| next.name.clone()),
43            new_ty: (previous.storage_ty != next.storage_ty).then(|| next.storage_ty.clone()),
44            new_not_null: (previous.nullable != next.nullable).then_some(!next.nullable),
45            new_auto_increment: (previous.auto_increment != next.auto_increment)
46                .then_some(next.auto_increment),
47        }
48    }
49
50    /// Splits up this set of changes into a [`Vec`] of individual changes.
51    pub fn split(self) -> Vec<Self> {
52        let Self {
53            new_name,
54            new_ty,
55            new_not_null,
56            new_auto_increment,
57        } = self;
58        let default = AlterColumnChanges {
59            new_name: None,
60            new_ty: None,
61            new_not_null: None,
62            new_auto_increment: None,
63        };
64        let mut result = vec![];
65        if new_name.is_some() {
66            result.push(Self {
67                new_name,
68                ..default.clone()
69            });
70        }
71        if new_ty.is_some() {
72            result.push(Self {
73                new_ty,
74                ..default.clone()
75            });
76        }
77        if new_not_null.is_some() {
78            result.push(Self {
79                new_not_null,
80                ..default.clone()
81            });
82        }
83        if new_auto_increment.is_some() {
84            result.push(Self {
85                new_auto_increment,
86                ..default.clone()
87            });
88        }
89        result
90    }
91
92    pub fn has_type_change(&self) -> bool {
93        self.new_ty.is_some() || self.new_not_null.is_some() || self.new_auto_increment.is_some()
94    }
95}
96
97impl Statement {
98    /// Alters a column.
99    pub fn alter_column(
100        column: &Column,
101        changes: AlterColumnChanges,
102        capability: &Capability,
103    ) -> Self {
104        AlterColumn {
105            id: column.id,
106            column_def: ColumnDef::from_schema(column, &capability.storage_types),
107            changes,
108        }
109        .into()
110    }
111}
112
113impl From<AlterColumn> for Statement {
114    fn from(value: AlterColumn) -> Self {
115        Self::AlterColumn(value)
116    }
117}