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
use {
	super::{validate, AlterError},
	crate::{data::get_name, Error, Glue, Result, SchemaDiff},
	sqlparser::ast::{AlterTableOperation, ObjectName},
};

impl Glue {
	pub async fn alter_table(
		&mut self,
		name: &ObjectName,
		operation: &AlterTableOperation,
	) -> Result<()> {
		let table_name = get_name(name).map_err(Error::from)?;
		let database = &mut **self.get_mut_database(&None)?;

		let diff = match operation {
			AlterTableOperation::RenameTable {
				table_name: new_table_name,
			} => {
				let new_table_name = get_name(new_table_name).map_err(Error::from)?;

				SchemaDiff::new_rename(new_table_name.clone())
			}
			AlterTableOperation::RenameColumn {
				old_column_name,
				new_column_name,
			} => {
				let schema = database
					.fetch_schema(table_name)
					.await?
					.ok_or(AlterError::TableNotFound(table_name.clone()))?;
				let (column_index, column) = schema
					.column_defs
					.into_iter()
					.enumerate()
					.find(|(_, column)| column.name == old_column_name.value)
					.ok_or(AlterError::ColumnNotFound(
						table_name.clone(),
						old_column_name.value.clone(),
					))?;
				SchemaDiff::new_rename_column(column_index, column, new_column_name.value.clone())
			}
			AlterTableOperation::AddColumn { column_def } => {
				validate(column_def).map_err(Error::from)?;

				SchemaDiff::new_add_column(column_def.into())
			}
			AlterTableOperation::DropColumn {
				column_name,
				if_exists: _,
				..
			} => {
				let schema = database
					.fetch_schema(table_name)
					.await?
					.ok_or(AlterError::TableNotFound(table_name.clone()))?;
				let (column_index, _) = schema
					.column_defs
					.into_iter()
					.enumerate()
					.find(|(_, column)| column.name == column_name.value)
					.ok_or(AlterError::ColumnNotFound(
						table_name.clone(),
						column_name.value.clone(),
					))?;

				SchemaDiff::new_remove_column(column_index)
			}
			_ => {
				return Err(
					AlterError::UnsupportedAlterTableOperation(operation.to_string()).into(),
				)
			}
		};
		database.alter_table(table_name, diff).await
	}
}