Skip to main content

rorm_sql/
alter_table.rs

1use std::fmt::Write;
2
3use crate::create_column::{CreateColumn, CreateColumnImpl};
4use crate::error::Error;
5use crate::Value;
6
7/**
8Representation of operations to execute in the context of an ALTER TABLE statement.
9 */
10#[derive(Debug)]
11pub enum AlterTableOperation<'until_build, 'post_build> {
12    /// Use this operation to rename a table
13    RenameTo {
14        /// New name of the table
15        name: String,
16    },
17    /// Use this operation to rename a column within a table
18    RenameColumnTo {
19        /// Current column name
20        column_name: String,
21        /// New column name
22        new_column_name: String,
23    },
24    /// Use this operation to add a column to an existing table.
25    AddColumn {
26        /// Operation to use for adding the column
27        operation: CreateColumnImpl<'until_build, 'post_build>,
28    },
29    /// Use this operation to drop an existing column.
30    DropColumn {
31        /// Name of the column to drop
32        name: String,
33    },
34}
35
36/**
37The trait representing an alter table builder
38*/
39pub trait AlterTable<'post_build> {
40    /**
41    This method is used to build the alter table statement.
42     */
43    fn build(self) -> Result<Vec<(String, Vec<Value<'post_build>>)>, Error>;
44}
45
46/**
47Representation of the data of an ALTER TABLE statement.
48 */
49#[derive(Debug)]
50pub struct AlterTableData<'until_build, 'post_build> {
51    /// Name of the table to operate on
52    pub(crate) name: &'until_build str,
53    /// Operation to execute
54    pub(crate) operation: AlterTableOperation<'until_build, 'post_build>,
55    pub(crate) lookup: Vec<Value<'post_build>>,
56    pub(crate) statements: Vec<(String, Vec<Value<'post_build>>)>,
57}
58
59/**
60Implementation of the [AlterTable] trait for the different database dialects.
61
62Should only be constructed via [crate::DBImpl::alter_table].
63 */
64#[derive(Debug)]
65pub enum AlterTableImpl<'until_build, 'post_build> {
66    /**
67    SQLite representation of the ALTER TABLE operation.
68     */
69    #[cfg(feature = "sqlite")]
70    SQLite(AlterTableData<'until_build, 'post_build>),
71    /**
72    Postgres representation of the ALTER TABLE operation.
73     */
74    #[cfg(feature = "postgres")]
75    Postgres(AlterTableData<'until_build, 'post_build>),
76}
77
78impl<'post_build> AlterTable<'post_build> for AlterTableImpl<'_, 'post_build> {
79    fn build(self) -> Result<Vec<(String, Vec<Value<'post_build>>)>, Error> {
80        match self {
81            #[cfg(feature = "sqlite")]
82            AlterTableImpl::SQLite(mut d) => {
83                let mut s = format!("ALTER TABLE \"{}\" ", d.name);
84
85                match d.operation {
86                    AlterTableOperation::RenameTo { name } => {
87                        write!(s, "RENAME TO \"{name}\"").unwrap();
88                    }
89                    AlterTableOperation::RenameColumnTo {
90                        column_name,
91                        new_column_name,
92                    } => write!(
93                        s,
94                        "RENAME COLUMN \"{column_name}\" TO \"{new_column_name}\""
95                    )
96                    .unwrap(),
97                    AlterTableOperation::AddColumn { mut operation } => {
98                        write!(s, "ADD COLUMN ").unwrap();
99
100                        if let CreateColumnImpl::SQLite(ccd) = &mut operation {
101                            ccd.statements = Some(&mut d.statements);
102                            ccd.lookup = Some(&mut d.lookup);
103                        }
104
105                        operation.build(&mut s)?;
106                    }
107                    AlterTableOperation::DropColumn { name } => {
108                        write!(s, "DROP COLUMN \"{name}\"").unwrap()
109                    }
110                };
111
112                write!(s, ";").unwrap();
113
114                let mut statements = vec![(s, d.lookup)];
115                statements.extend(d.statements);
116
117                Ok(statements)
118            }
119            #[cfg(feature = "postgres")]
120            AlterTableImpl::Postgres(mut d) => {
121                let mut s = format!("ALTER TABLE \"{}\" ", d.name);
122
123                match d.operation {
124                    AlterTableOperation::RenameTo { name } => {
125                        write!(s, "RENAME TO \"{name}\"").unwrap();
126                    }
127
128                    AlterTableOperation::RenameColumnTo {
129                        column_name,
130                        new_column_name,
131                    } => {
132                        write!(
133                            s,
134                            "RENAME COLUMN \"{column_name}\" TO \"{new_column_name}\""
135                        )
136                        .unwrap();
137                    }
138                    AlterTableOperation::AddColumn { mut operation } => {
139                        write!(s, "ADD COLUMN ").unwrap();
140
141                        #[allow(irrefutable_let_patterns)]
142                        if let CreateColumnImpl::Postgres(ccd) = &mut operation {
143                            ccd.statements = Some(&mut d.statements);
144                        }
145
146                        operation.build(&mut s)?;
147                    }
148                    AlterTableOperation::DropColumn { name } => {
149                        write!(s, "DROP COLUMN \"{name}\"").unwrap()
150                    }
151                };
152
153                write!(s, ";").unwrap();
154
155                let mut statements = vec![(s, d.lookup)];
156                statements.extend(d.statements);
157
158                Ok(statements)
159            }
160        }
161    }
162}