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