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