gluesql_test_suite/alter/
alter_table.rs

1use {
2    crate::*,
3    gluesql_core::{
4        ast::*,
5        data::Value::*,
6        error::{AlterError, AlterTableError, EvaluateError, TranslateError},
7        executor::Referencing,
8        prelude::Payload,
9    },
10};
11
12test_case!(alter_table_rename, {
13    let g = get_tester!();
14
15    let test_cases = [
16        (
17            "CREATE TABLE Foo (id INTEGER, name TEXT);",
18            Ok(Payload::Create),
19        ),
20        (
21            "INSERT INTO Foo VALUES (1, 'a'), (2, 'b'), (3, 'c');",
22            Ok(Payload::Insert(3)),
23        ),
24        ("SELECT id FROM Foo", Ok(select!(id; I64; 1; 2; 3))),
25        (
26            "ALTER TABLE Foo2 RENAME TO Bar;",
27            Err(AlterTableError::TableNotFound("Foo2".to_owned()).into()),
28        ),
29        ("ALTER TABLE Foo RENAME TO Bar;", Ok(Payload::AlterTable)),
30        ("SELECT id FROM Bar", Ok(select!(id; I64; 1; 2; 3))),
31        (
32            "ALTER TABLE Bar RENAME COLUMN id TO new_id",
33            Ok(Payload::AlterTable),
34        ),
35        ("SELECT new_id FROM Bar", Ok(select!(new_id; I64; 1; 2; 3))),
36        (
37            "ALTER TABLE Bar RENAME COLUMN hello TO idid",
38            Err(AlterTableError::RenamingColumnNotFound.into()),
39        ),
40        (
41            // Cannot rename to duplicated column name
42            "ALTER TABLE Bar RENAME COLUMN name TO new_id",
43            Err(AlterTableError::AlreadyExistingColumn("new_id".to_owned()).into()),
44        ),
45    ];
46
47    for (sql, expected) in test_cases {
48        g.test(sql, expected).await;
49    }
50});
51
52test_case!(alter_table_add_drop, {
53    let g = get_tester!();
54
55    let test_cases = [
56        ("CREATE TABLE Foo (id INTEGER);", Ok(Payload::Create)),
57        ("INSERT INTO Foo VALUES (1), (2);", Ok(Payload::Insert(2))),
58        ("SELECT * FROM Foo;", Ok(select!(id; I64; 1; 2))),
59        (
60            "ALTER TABLE Foo ADD COLUMN amount INTEGER NOT NULL",
61            Err(AlterTableError::DefaultValueRequired(ColumnDef {
62                name: "amount".to_owned(),
63                data_type: DataType::Int,
64                nullable: false,
65                default: None,
66                unique: None,
67                comment: None,
68            })
69            .into()),
70        ),
71        (
72            "ALTER TABLE Foo ADD COLUMN id INTEGER",
73            Err(AlterTableError::AlreadyExistingColumn("id".to_owned()).into()),
74        ),
75        (
76            "ALTER TABLE Foo ADD COLUMN amount INTEGER DEFAULT 10",
77            Ok(Payload::AlterTable),
78        ),
79        (
80            "SELECT * FROM Foo;",
81            Ok(select!(id | amount; I64 | I64; 1 10; 2 10)),
82        ),
83        (
84            "ALTER TABLE Foo ADD COLUMN opt BOOLEAN NULL",
85            Ok(Payload::AlterTable),
86        ),
87        (
88            "SELECT * FROM Foo;",
89            Ok(select_with_null!(
90                id     | amount  | opt;
91                I64(1)   I64(10)   Null;
92                I64(2)   I64(10)   Null
93            )),
94        ),
95        (
96            "ALTER TABLE Foo ADD COLUMN opt2 BOOLEAN NULL DEFAULT true",
97            Ok(Payload::AlterTable),
98        ),
99        (
100            "SELECT * FROM Foo;",
101            Ok(select_with_null!(
102                id     | amount  | opt  | opt2;
103                I64(1)   I64(10)   Null   Bool(true);
104                I64(2)   I64(10)   Null   Bool(true)
105            )),
106        ),
107        (
108            "ALTER TABLE Foo ADD COLUMN something INTEGER DEFAULT (SELECT id FROM Bar LIMIT 1)",
109            Err(EvaluateError::UnsupportedStatelessExpr(Box::new(expr(
110                "(SELECT id FROM Bar LIMIT 1)",
111            )))
112            .into()),
113        ),
114        (
115            "ALTER TABLE Foo ADD COLUMN something SOMEWHAT",
116            Err(TranslateError::UnsupportedDataType("SOMEWHAT".to_owned()).into()),
117        ),
118        (
119            "ALTER TABLE Foo ADD COLUMN something FLOAT UNIQUE",
120            Err(AlterError::UnsupportedDataTypeForUniqueColumn(
121                "something".to_owned(),
122                DataType::Float,
123            )
124            .into()),
125        ),
126        (
127            "ALTER TABLE Foo DROP COLUMN IF EXISTS something;",
128            Ok(Payload::AlterTable),
129        ),
130        (
131            "ALTER TABLE Foo DROP COLUMN something;",
132            Err(AlterTableError::DroppingColumnNotFound("something".to_owned()).into()),
133        ),
134        (
135            "ALTER TABLE Foo DROP COLUMN amount;",
136            Ok(Payload::AlterTable),
137        ),
138        (
139            "SELECT * FROM Foo;",
140            Ok(select_with_null!(
141                id     | opt  | opt2;
142                I64(1)   Null   Bool(true);
143                I64(2)   Null   Bool(true)
144            )),
145        ),
146        (
147            "ALTER TABLE Foo DROP COLUMN IF EXISTS opt2;",
148            Ok(Payload::AlterTable),
149        ),
150        (
151            "SELECT * FROM Foo;",
152            Ok(select_with_null!(
153                id     | opt;
154                I64(1)   Null;
155                I64(2)   Null
156            )),
157        ),
158        (
159            r#"ALTER TABLE Foo ADD CONSTRAINT "hey" PRIMARY KEY (asdf);"#,
160            Err(TranslateError::UnsupportedAlterTableOperation(
161                r#"ADD CONSTRAINT "hey" PRIMARY KEY (asdf)"#.to_owned(),
162            )
163            .into()),
164        ),
165        (
166            "ALTER TABLE Foo ADD CONSTRAINT hello UNIQUE (id)",
167            Err(TranslateError::UnsupportedAlterTableOperation(
168                "ADD CONSTRAINT hello UNIQUE (id)".to_owned(),
169            )
170            .into()),
171        ),
172        (
173            "CREATE TABLE Referenced (id INTEGER PRIMARY KEY);",
174            Ok(Payload::Create),
175        ),
176        (
177            "CREATE TABLE Referencing (
178                id INTEGER,
179                referenced_id INTEGER,
180                FOREIGN KEY (referenced_id) REFERENCES Referenced (id)
181          );",
182            Ok(Payload::Create),
183        ),
184        (
185            "ALTER TABLE Referenced DROP COLUMN id",
186            Err(AlterError::CannotAlterReferencedColumn {
187                referencing: Referencing {
188                    table_name: "Referencing".to_owned(),
189                    foreign_key: ForeignKey {
190                        name: "FK_referenced_id-Referenced_id".to_owned(),
191                        referencing_column_name: "referenced_id".to_owned(),
192                        referenced_table_name: "Referenced".to_owned(),
193                        referenced_column_name: "id".to_owned(),
194                        on_delete: ReferentialAction::NoAction,
195                        on_update: ReferentialAction::NoAction,
196                    },
197                },
198            }
199            .into()),
200        ),
201        (
202            "ALTER TABLE Referenced RENAME COLUMN id to new_id",
203            Err(AlterError::CannotAlterReferencedColumn {
204                referencing: Referencing {
205                    table_name: "Referencing".to_owned(),
206                    foreign_key: ForeignKey {
207                        name: "FK_referenced_id-Referenced_id".to_owned(),
208                        referencing_column_name: "referenced_id".to_owned(),
209                        referenced_table_name: "Referenced".to_owned(),
210                        referenced_column_name: "id".to_owned(),
211                        on_delete: ReferentialAction::NoAction,
212                        on_update: ReferentialAction::NoAction,
213                    },
214                },
215            }
216            .into()),
217        ),
218        (
219            "ALTER TABLE Referencing DROP COLUMN referenced_id",
220            Err(AlterError::CannotAlterReferencingColumn {
221                referencing: Referencing {
222                    table_name: "Referencing".to_owned(),
223                    foreign_key: ForeignKey {
224                        name: "FK_referenced_id-Referenced_id".to_owned(),
225                        referencing_column_name: "referenced_id".to_owned(),
226                        referenced_table_name: "Referenced".to_owned(),
227                        referenced_column_name: "id".to_owned(),
228                        on_delete: ReferentialAction::NoAction,
229                        on_update: ReferentialAction::NoAction,
230                    },
231                },
232            }
233            .into()),
234        ),
235        (
236            "ALTER TABLE Referencing RENAME COLUMN referenced_id to new_id",
237            Err(AlterError::CannotAlterReferencingColumn {
238                referencing: Referencing {
239                    table_name: "Referencing".to_owned(),
240                    foreign_key: ForeignKey {
241                        name: "FK_referenced_id-Referenced_id".to_owned(),
242                        referencing_column_name: "referenced_id".to_owned(),
243                        referenced_table_name: "Referenced".to_owned(),
244                        referenced_column_name: "id".to_owned(),
245                        on_delete: ReferentialAction::NoAction,
246                        on_update: ReferentialAction::NoAction,
247                    },
248                },
249            }
250            .into()),
251        ),
252    ];
253
254    for (sql, expected) in test_cases {
255        g.test(sql, expected).await;
256    }
257});