Skip to main content

datasources_sqlite/
statement_renderer.rs

1use crate::alter_table_statement_renderer::SqliteAlterTableStatementRenderer;
2use crate::create_table_statement_renderer::SqliteCreateTableStatementRenderer;
3use crate::create_trigger_statement_renderer::SqliteCreateTriggerStatementRenderer;
4use crate::select_inserted_id_statement_text_renderer::SqliteSelectInsertedIdStatementTextRenderer;
5use crate::quoted_renderers::{
6    SqliteCreateIndexStatementRenderer, SqliteDropIndexStatementRenderer,
7    SqliteDropTableStatementRenderer, SqliteDropTriggerStatementRenderer,
8    SqliteForeignKeyStatementRenderer,
9};
10use crate::sql_seed_statement_renderer::SqliteSqlSeedStatementRenderer;
11use datasources::{
12    AlterTableStatement, CreateIndexStatement, CreateTableStatement, CreateTableStatementTextRenderer,
13    CreateTriggerStatement, DropIndexStatement, DropTableStatement, DropTriggerStatement,
14    ForeignKeyStatement, ProcedureSource, SelectInsertedIdStatement, SqlSeedStatement,
15    sql_procedure_statements_of, Statement, StatementTextRenderer, StatementVisitor,
16};
17
18pub struct SqliteStatementRenderer;
19
20impl StatementVisitor for SqliteStatementRenderer {
21    fn procedures(&self, source: &ProcedureSource) -> Vec<Box<dyn Statement>> {
22        sql_procedure_statements_of(source)
23    }
24
25    fn visit_create_table(
26        &self,
27        statement: &CreateTableStatement,
28        _text: &StatementTextRenderer,
29    ) -> String {
30        SqliteCreateTableStatementRenderer.render(statement)
31    }
32
33    fn visit_alter_table(
34        &self,
35        statement: &AlterTableStatement,
36        _text: &StatementTextRenderer,
37    ) -> String {
38        SqliteAlterTableStatementRenderer.render(statement)
39    }
40
41    fn visit_create_trigger(
42        &self,
43        statement: &CreateTriggerStatement,
44        _text: &StatementTextRenderer,
45    ) -> String {
46        SqliteCreateTriggerStatementRenderer.render(statement)
47    }
48
49    fn visit_select_inserted_id(
50        &self,
51        statement: &SelectInsertedIdStatement,
52        _text: &StatementTextRenderer,
53    ) -> String {
54        SqliteSelectInsertedIdStatementTextRenderer.render(statement)
55    }
56
57    fn visit_sql_seed(&self, statement: &SqlSeedStatement, _text: &StatementTextRenderer) -> String {
58        SqliteSqlSeedStatementRenderer.render(statement)
59    }
60
61    fn visit_drop_table(&self, statement: &DropTableStatement, _text: &StatementTextRenderer) -> String {
62        SqliteDropTableStatementRenderer.render(statement)
63    }
64
65    fn visit_create_index(&self, statement: &CreateIndexStatement, _text: &StatementTextRenderer) -> String {
66        SqliteCreateIndexStatementRenderer.render(statement)
67    }
68
69    fn visit_drop_index(&self, statement: &DropIndexStatement, _text: &StatementTextRenderer) -> String {
70        SqliteDropIndexStatementRenderer.render(statement)
71    }
72
73    fn visit_drop_trigger(&self, statement: &DropTriggerStatement, _text: &StatementTextRenderer) -> String {
74        SqliteDropTriggerStatementRenderer.render(statement)
75    }
76
77    fn visit_foreign_key(&self, statement: &ForeignKeyStatement, _text: &StatementTextRenderer) -> String {
78        SqliteForeignKeyStatementRenderer.render(statement)
79    }
80}
81
82#[cfg(test)]
83mod tests {
84    use super::SqliteStatementRenderer;
85    use crate::create_table_statement_renderer::SqliteCreateTableStatementRenderer;
86    use datasources::{
87        Column, ColumnDefault, CreateTableStatement, CreateTableStatementTextRenderer,
88        DefaultStatementTextRenderer, ForeignKey, NotNull, PrimaryKey, ReferentialAction,
89        SelectInsertedIdStatement, SelectStatement, SelectStatementOptions, StatementTextRenderer,
90    };
91
92    fn renderer() -> StatementTextRenderer {
93        StatementTextRenderer::new(Some(Box::new(SqliteStatementRenderer)), None)
94    }
95
96    #[test]
97    fn renders_inserted_id_and_create_table() {
98        let statements = renderer();
99        assert_eq!(
100            statements.render(&SelectInsertedIdStatement::new("users", "id")),
101            "SELECT last_insert_rowid() AS id"
102        );
103
104        let columns = [
105            Column::new("id", "INTEGER")
106                .default(ColumnDefault::new("0", Some("df_id")))
107                .not_null(NotNull::new(Some("nn_id"))),
108            Column::new("user_id", "INTEGER"),
109        ];
110        let constraints = [
111            PrimaryKey::new("pk_orders", &["id"]),
112            ForeignKey::new(
113                "fk_orders_user",
114                &["user_id"],
115                "users",
116                &["id"],
117                Some(ReferentialAction::Cascade),
118                None,
119            ),
120        ];
121        let create = CreateTableStatement::new("orders", &columns, &constraints);
122        assert_eq!(
123            statements.render(&create),
124            SqliteCreateTableStatementRenderer.render(&create)
125        );
126        assert_eq!(
127            statements.render(&SelectStatement::new(SelectStatementOptions::new(
128                "users",
129                &["id"]
130            ))),
131            "SELECT id FROM users"
132        );
133    }
134
135    #[test]
136    fn renders_canonical_types() {
137        let columns = [Column::new("id", "int")
138            .identity()
139            .default(ColumnDefault::new("0", None))
140            .not_null(NotNull::new(None))];
141        let create = CreateTableStatement::new("users", &columns, &[]);
142        assert_eq!(
143            renderer().render(&create),
144            "CREATE TABLE \"users\" (\n    \"id\" INTEGER PRIMARY KEY AUTOINCREMENT DEFAULT 0 NOT NULL\n)"
145        );
146        assert_eq!(
147            DefaultStatementTextRenderer::instance().render(&create),
148            "CREATE TABLE users (\n    id int DEFAULT 0 NOT NULL\n)"
149        );
150
151        let keyed = CreateTableStatement::new(
152            "users",
153            &[Column::new("id", "int").identity()],
154            &[PrimaryKey::new("pk_users", &["id"])],
155        );
156        assert_eq!(
157            renderer().render(&keyed),
158            "CREATE TABLE \"users\" (\n    \"id\" INTEGER PRIMARY KEY AUTOINCREMENT\n)"
159        );
160    }
161
162    #[test]
163    fn renders_alter_add_column() {
164        use datasources::{AlterAction, AlterTableStatement, NotNull};
165        let alter = AlterTableStatement::new(
166            "users",
167            AlterAction::AddColumn(Column::new("email", "TEXT").not_null(NotNull::new(None))),
168        );
169        assert_eq!(
170            renderer().render(&alter),
171            "ALTER TABLE \"users\" ADD COLUMN \"email\" TEXT NOT NULL"
172        );
173    }
174
175    #[test]
176    #[should_panic(expected = "SQLite cannot ALTER COLUMN")]
177    fn throws_on_alter_column() {
178        use datasources::{AlterAction, AlterTableStatement};
179        let alter = AlterTableStatement::new("users", AlterAction::AlterColumn(Column::new("age", "INTEGER")));
180        renderer().render(&alter);
181    }
182}