rorm_sql/
lib.rs

1//! The module should be used to create sql queries for different SQL dialects.
2#![cfg_attr(all(doc, CHANNEL_NIGHTLY), feature(doc_auto_cfg))]
3#![warn(missing_docs)]
4
5#[cfg(not(any(feature = "sqlite", feature = "postgres", feature = "mysql")))]
6compile_error!("One of the features sqlite, postgres, mysql must be activated");
7
8/// Implementation of a aggregator functions
9pub mod aggregation;
10/// Implementation of SQL ALTER TABLE statements
11pub mod alter_table;
12///This module defines the conditional statements
13pub mod conditional;
14/// Implementation of SQL CREATE COLUMN statements
15pub mod create_column;
16/// Implementation of SQL CREATE INDEX
17pub mod create_index;
18/// Implementation of SQL CREATE TABLE statements
19pub mod create_table;
20/// Implementation of SQL CREATE TRIGGER statements
21pub mod create_trigger;
22/// Implementation of SQL DELETE operation
23pub mod delete;
24/// Implementation of SQL DROP TABLE statements
25pub mod drop_table;
26/// Definition of error types that can occur.
27pub mod error;
28/// Implementation of SQL INSERT statements
29pub mod insert;
30/// Implementation of JOIN statements
31pub mod join_table;
32/// Implementation of limit clauses
33pub mod limit_clause;
34/// Implementation of SQL ON CONFLICT extensions
35pub mod on_conflict;
36/// Implementation of ORDER BY expressions
37pub mod ordering;
38/// Implementation of SQL SELECT statements
39pub mod select;
40/// Implementation of identifiers in select queries
41pub mod select_column;
42/// Implementation of SQL UPDATE statements
43pub mod update;
44/// Implementation of supported datatypes
45pub mod value;
46
47mod db_specific;
48
49use rorm_declaration::imr::Annotation;
50use rorm_declaration::imr::DbType;
51
52use crate::aggregation::SelectAggregator;
53use crate::alter_table::AlterTable;
54use crate::alter_table::AlterTableData;
55use crate::alter_table::AlterTableImpl;
56use crate::alter_table::AlterTableOperation;
57use crate::conditional::Condition;
58use crate::create_column::CreateColumnImpl;
59#[cfg(feature = "mysql")]
60use crate::create_column::CreateColumnMySQLData;
61#[cfg(feature = "postgres")]
62use crate::create_column::CreateColumnPostgresData;
63#[cfg(feature = "sqlite")]
64use crate::create_column::CreateColumnSQLiteData;
65use crate::create_column::SQLAnnotation;
66use crate::create_index::CreateIndex;
67use crate::create_index::CreateIndexData;
68use crate::create_index::CreateIndexImpl;
69use crate::create_table::CreateTable;
70use crate::create_table::CreateTableData;
71use crate::create_table::CreateTableImpl;
72use crate::create_trigger::SQLCreateTrigger;
73use crate::create_trigger::SQLCreateTriggerOperation;
74use crate::create_trigger::SQLCreateTriggerPointInTime;
75use crate::delete::Delete;
76use crate::delete::DeleteData;
77use crate::delete::DeleteImpl;
78use crate::drop_table::DropTable;
79use crate::drop_table::DropTableData;
80use crate::drop_table::DropTableImpl;
81use crate::insert::Insert;
82use crate::insert::InsertData;
83use crate::insert::InsertImpl;
84use crate::join_table::JoinTableData;
85use crate::join_table::JoinTableImpl;
86use crate::join_table::JoinType;
87use crate::on_conflict::OnConflict;
88use crate::ordering::OrderByEntry;
89use crate::select::Select;
90use crate::select::SelectData;
91use crate::select::SelectImpl;
92use crate::select_column::SelectColumnData;
93use crate::select_column::SelectColumnImpl;
94use crate::update::Update;
95use crate::update::UpdateData;
96use crate::update::UpdateImpl;
97use crate::value::Value;
98
99/**
100The main interface for creating sql strings
101*/
102#[derive(Copy, Clone)]
103pub enum DBImpl {
104    /// Implementation of SQLite
105    #[cfg(feature = "sqlite")]
106    SQLite,
107    /// Implementation of Postgres
108    #[cfg(feature = "postgres")]
109    Postgres,
110    /// Implementation of MySQL / MariaDB
111    #[cfg(feature = "mysql")]
112    MySQL,
113}
114
115impl DBImpl {
116    /**
117    The entry point to create a table.
118
119    **Parameter**:
120    - `name`: Name of the table
121    */
122    pub fn create_table<'until_build, 'post_build>(
123        &self,
124        name: &'until_build str,
125    ) -> impl CreateTable<'until_build, 'post_build>
126    where
127        'post_build: 'until_build,
128    {
129        let d = CreateTableData {
130            name,
131            columns: vec![],
132            if_not_exists: false,
133            lookup: vec![],
134            pre_statements: vec![],
135            statements: vec![],
136        };
137
138        match self {
139            #[cfg(feature = "sqlite")]
140            DBImpl::SQLite => CreateTableImpl::SQLite(d),
141            #[cfg(feature = "mysql")]
142            DBImpl::MySQL => CreateTableImpl::MySQL(d),
143            #[cfg(feature = "postgres")]
144            DBImpl::Postgres => CreateTableImpl::Postgres(d),
145        }
146    }
147
148    /**
149    The entry point to create a trigger.
150
151    **Parameter**:
152    - `name`: Name of the trigger.
153    - `table_name`: Name of the table to create the trigger on.
154    - `point_in_time`: [Option] of [SQLCreateTriggerPointInTime]: When to execute the trigger.
155    - `operation`: [SQLCreateTriggerOperation]: The operation that invokes the trigger.
156    */
157    pub fn create_trigger(
158        &self,
159        name: &str,
160        table_name: &str,
161        point_in_time: Option<SQLCreateTriggerPointInTime>,
162        operation: SQLCreateTriggerOperation,
163    ) -> SQLCreateTrigger {
164        SQLCreateTrigger {
165            name: name.to_string(),
166            table_name: table_name.to_string(),
167            if_not_exists: false,
168            point_in_time,
169            operation,
170            statements: vec![],
171            for_each_row: false,
172        }
173    }
174
175    /**
176    The entry point to create an index.
177
178    **Parameter**:
179    - `name`: Name of the index.
180    - `table_name`: Table to create the index on.
181    */
182    pub fn create_index<'until_build>(
183        &self,
184        name: &'until_build str,
185        table_name: &'until_build str,
186    ) -> impl CreateIndex<'until_build> {
187        let d = CreateIndexData {
188            name,
189            table_name,
190            unique: false,
191            if_not_exists: false,
192            columns: vec![],
193            condition: None,
194        };
195
196        match self {
197            #[cfg(feature = "sqlite")]
198            DBImpl::SQLite => CreateIndexImpl::Sqlite(d),
199            #[cfg(feature = "mysql")]
200            DBImpl::MySQL => CreateIndexImpl::MySQL(d),
201            #[cfg(feature = "postgres")]
202            DBImpl::Postgres => CreateIndexImpl::Postgres(d),
203        }
204    }
205
206    /**
207    The entry point to drop a table.
208
209    **Parameter**:
210    - `name`: Name of the table to drop.
211    */
212    pub fn drop_table<'until_build>(
213        &self,
214        name: &'until_build str,
215    ) -> impl DropTable + 'until_build {
216        let d = DropTableData {
217            name,
218            if_exists: false,
219        };
220        match self {
221            #[cfg(feature = "sqlite")]
222            DBImpl::SQLite => DropTableImpl::SQLite(d),
223            #[cfg(feature = "mysql")]
224            DBImpl::MySQL => DropTableImpl::MySQL(d),
225            #[cfg(feature = "postgres")]
226            DBImpl::Postgres => DropTableImpl::Postgres(d),
227        }
228    }
229
230    /**
231    The entry point to alter a table.
232
233    **Parameter**:
234    - `name`: Name of the table to execute the operation on.
235    - `operation`: [AlterTableOperation]: The operation to execute.
236    */
237    pub fn alter_table<'until_build, 'post_build>(
238        &self,
239        name: &'until_build str,
240        operation: AlterTableOperation<'until_build, 'post_build>,
241    ) -> impl AlterTable<'post_build> + 'until_build
242    where
243        'post_build: 'until_build,
244    {
245        let d = AlterTableData {
246            name,
247            operation,
248            lookup: vec![],
249            statements: vec![],
250        };
251
252        match self {
253            #[cfg(feature = "sqlite")]
254            DBImpl::SQLite => AlterTableImpl::SQLite(d),
255            #[cfg(feature = "mysql")]
256            DBImpl::MySQL => AlterTableImpl::MySQL(d),
257            #[cfg(feature = "postgres")]
258            DBImpl::Postgres => AlterTableImpl::Postgres(d),
259        }
260    }
261
262    /**
263    The entry point to create a column in a table.
264
265    **Parameter**:
266    - `table_name`: Name of the table.
267    - `name`: Name of the column.
268    - `data_type`: [DbType]: Data type of the column
269    - `annotations`: slice of [Annotation]: List of annotations.
270    */
271    pub fn create_column<'until_build, 'post_build>(
272        &self,
273        table_name: &'until_build str,
274        name: &'until_build str,
275        data_type: DbType,
276        annotations: &'post_build [Annotation],
277    ) -> CreateColumnImpl<'until_build, 'post_build> {
278        #[cfg(not(any(feature = "postgres", feature = "sqlite")))]
279        let _ = table_name;
280
281        // Sort the annotations
282        let mut a = vec![];
283
284        for x in annotations {
285            if x.eq_shallow(&Annotation::PrimaryKey) {
286                a.push(SQLAnnotation { annotation: x });
287            }
288        }
289
290        for x in annotations {
291            if !x.eq_shallow(&Annotation::PrimaryKey) {
292                a.push(SQLAnnotation { annotation: x });
293            }
294        }
295
296        match self {
297            #[cfg(feature = "sqlite")]
298            DBImpl::SQLite => CreateColumnImpl::SQLite(CreateColumnSQLiteData {
299                name,
300                table_name,
301                data_type,
302                annotations: a,
303                statements: None,
304                lookup: None,
305            }),
306            #[cfg(feature = "mysql")]
307            DBImpl::MySQL => CreateColumnImpl::MySQL(CreateColumnMySQLData {
308                name,
309                data_type,
310                annotations: a,
311                statements: None,
312                lookup: None,
313            }),
314            #[cfg(feature = "postgres")]
315            DBImpl::Postgres => CreateColumnImpl::Postgres(CreateColumnPostgresData {
316                name,
317                table_name,
318                data_type,
319                annotations: a,
320                pre_statements: None,
321                statements: None,
322            }),
323        }
324    }
325
326    /**
327    Build a select query.
328
329    **Parameter**:
330    - `columns`: The columns to select.
331    - `from_clause`: Specifies from what to select. This can be a table name or another query itself.
332    - `joins`: List of join tables.
333    */
334    pub fn select<'until_build, 'post_build>(
335        &self,
336        columns: &'until_build [SelectColumnImpl],
337        from_clause: &'until_build str,
338        joins: &'until_build [JoinTableImpl<'until_build, 'post_build>],
339        order_by_clause: &'until_build [OrderByEntry<'until_build>],
340    ) -> impl Select<'until_build, 'post_build> {
341        let d = SelectData {
342            join_tables: joins,
343            resulting_columns: columns,
344            limit: None,
345            offset: None,
346            from_clause,
347            where_clause: None,
348            distinct: false,
349            lookup: vec![],
350            order_by_clause,
351        };
352        match self {
353            #[cfg(feature = "sqlite")]
354            DBImpl::SQLite => SelectImpl::SQLite(d),
355            #[cfg(feature = "mysql")]
356            DBImpl::MySQL => SelectImpl::MySQL(d),
357            #[cfg(feature = "postgres")]
358            DBImpl::Postgres => SelectImpl::Postgres(d),
359        }
360    }
361
362    /**
363    Build an INSERT query.
364
365    **Parameter**:
366    - `into_clause`: The table to insert into.
367    - `insert_columns`: The column names to insert into.
368    - `insert_values`: slice of slice of [Value]: The values to insert.
369    - `returning_clause`: Optional slice of string to retrieve after the insert.
370    */
371    pub fn insert<'until_build, 'post_build>(
372        &self,
373        into_clause: &'until_build str,
374        insert_columns: &'until_build [&'until_build str],
375        insert_values: &'until_build [&'until_build [Value<'post_build>]],
376        returning_clause: Option<&'until_build [&'until_build str]>,
377    ) -> impl Insert<'post_build> + 'until_build
378    where
379        'post_build: 'until_build,
380    {
381        let d = InsertData {
382            into_clause,
383            columns: insert_columns,
384            row_values: insert_values,
385            lookup: vec![],
386            on_conflict: OnConflict::ABORT,
387            returning_clause,
388        };
389        match self {
390            #[cfg(feature = "sqlite")]
391            DBImpl::SQLite => InsertImpl::SQLite(d),
392            #[cfg(feature = "mysql")]
393            DBImpl::MySQL => InsertImpl::MySQL(d),
394            #[cfg(feature = "postgres")]
395            DBImpl::Postgres => InsertImpl::Postgres(d),
396        }
397    }
398
399    /**
400    Build a delete operation.
401
402    **Parameter**:
403    - `table_name`: Name of the table to delete from.
404    */
405    pub fn delete<'until_build, 'post_query>(
406        &self,
407        table_name: &'until_build str,
408    ) -> impl Delete<'until_build, 'post_query>
409    where
410        'post_query: 'until_build,
411    {
412        let d = DeleteData {
413            model: table_name,
414            lookup: vec![],
415            where_clause: None,
416        };
417        match self {
418            #[cfg(feature = "sqlite")]
419            DBImpl::SQLite => DeleteImpl::SQLite(d),
420            #[cfg(feature = "mysql")]
421            DBImpl::MySQL => DeleteImpl::MySQL(d),
422            #[cfg(feature = "postgres")]
423            DBImpl::Postgres => DeleteImpl::Postgres(d),
424        }
425    }
426
427    /**
428    Build an update operation.
429
430    **Parameter**:
431    - `table_name`: Name of the table the updates should be executed for.
432    */
433    pub fn update<'until_build, 'post_query>(
434        &self,
435        table_name: &'until_build str,
436    ) -> impl Update<'until_build, 'post_query>
437    where
438        'post_query: 'until_build,
439    {
440        let d = UpdateData {
441            model: table_name,
442            on_conflict: OnConflict::ABORT,
443            updates: vec![],
444            where_clause: None,
445            lookup: vec![],
446        };
447        match self {
448            #[cfg(feature = "sqlite")]
449            DBImpl::SQLite => UpdateImpl::SQLite(d),
450            #[cfg(feature = "mysql")]
451            DBImpl::MySQL => UpdateImpl::MySQL(d),
452            #[cfg(feature = "postgres")]
453            DBImpl::Postgres => UpdateImpl::Postgres(d),
454        }
455    }
456
457    /**
458    The entry point for a JOIN expression builder.
459
460    **Parameter**:
461    - `join_type`: [JoinType]: Type for a JOIN expression
462    - `table_name`: Table to perform the join on
463    - `join_alias`: Alias for the join table
464    - `join_condition`: [Condition] to apply to the join
465    */
466    pub fn join_table<'until_build, 'post_query>(
467        &self,
468        join_type: JoinType,
469        table_name: &'until_build str,
470        join_alias: &'until_build str,
471        join_condition: &'until_build Condition<'post_query>,
472    ) -> JoinTableImpl<'until_build, 'post_query> {
473        let d = JoinTableData {
474            join_type,
475            table_name,
476            join_alias,
477            join_condition,
478        };
479
480        match self {
481            #[cfg(feature = "sqlite")]
482            DBImpl::SQLite => JoinTableImpl::SQLite(d),
483            #[cfg(feature = "mysql")]
484            DBImpl::MySQL => JoinTableImpl::MySQL(d),
485            #[cfg(feature = "postgres")]
486            DBImpl::Postgres => JoinTableImpl::Postgres(d),
487        }
488    }
489
490    /**
491    The entry point for a column selector builder.
492
493    **Parameter**:
494    - `table_name`: Optional table name
495    - `column_name`: Name of the column
496    - `select_alias`: Alias for the selector
497    - `aggregation`: Optional aggregation function
498     */
499    pub fn select_column<'until_build>(
500        &self,
501        table_name: Option<&'until_build str>,
502        column_name: &'until_build str,
503        select_alias: Option<&'until_build str>,
504        aggregation: Option<SelectAggregator>,
505    ) -> SelectColumnImpl<'until_build> {
506        let d = SelectColumnData {
507            table_name,
508            column_name,
509            select_alias,
510            aggregation,
511        };
512
513        match self {
514            #[cfg(feature = "sqlite")]
515            DBImpl::SQLite => SelectColumnImpl::SQLite(d),
516            #[cfg(feature = "mysql")]
517            DBImpl::MySQL => SelectColumnImpl::MySQL(d),
518            #[cfg(feature = "postgres")]
519            DBImpl::Postgres => SelectColumnImpl::Postgres(d),
520        }
521    }
522}