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