Skip to main content

rorm_sql/
lib.rs

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