sea_query/
lib.rs

1#![cfg_attr(docsrs, feature(doc_cfg))]
2#![deny(missing_debug_implementations)]
3
4//! <div align="center">
5//!
6//!   <img src="https://raw.githubusercontent.com/SeaQL/sea-query/master/docs/SeaQuery logo.png" width="280" alt="SeaQuery logo"/>
7//!
8//!   <p>
9//!     <strong>🔱 A dynamic query builder for MySQL, Postgres and SQLite</strong>
10//!   </p>
11//!
12//!   [![crate](https://img.shields.io/crates/v/sea-query.svg)](https://crates.io/crates/sea-query)
13//!   [![docs](https://docs.rs/sea-query/badge.svg)](https://docs.rs/sea-query)
14//!   [![build status](https://github.com/SeaQL/sea-query/actions/workflows/rust.yml/badge.svg)](https://github.com/SeaQL/sea-query/actions/workflows/rust.yml)
15//!
16//! </div>
17//!
18//! ## SeaQuery
19//!
20//! SeaQuery is a query builder to help you construct dynamic SQL queries in Rust.
21//! You can construct expressions, queries and schema as abstract syntax trees using an ergonomic API.
22//! We support MySQL, Postgres and SQLite behind a common interface that aligns their behaviour where appropriate.
23//!
24//! We provide integration for [SQLx](https://crates.io/crates/sqlx),
25//! [postgres](https://crates.io/crates/postgres) and [rusqlite](https://crates.io/crates/rusqlite).
26//! See [examples](https://github.com/SeaQL/sea-query/blob/master/examples) for usage.
27//!
28//! SeaQuery is the foundation of [SeaORM](https://github.com/SeaQL/sea-orm), an async & dynamic ORM for Rust.
29//!
30//! [![GitHub stars](https://img.shields.io/github/stars/SeaQL/sea-query.svg?style=social&label=Star&maxAge=1)](https://github.com/SeaQL/sea-query/stargazers/)
31//! If you like what we do, consider starring, commenting, sharing and contributing!
32//!
33//! [![Discord](https://img.shields.io/discord/873880840487206962?label=Discord)](https://discord.com/invite/uCPdDXzbdv)
34//! Join our Discord server to chat with others in the SeaQL community!
35//!
36//! ## Install
37//!
38//! ```toml
39//! # Cargo.toml
40//! [dependencies]
41//! sea-query = "0"
42//! ```
43//!
44//! SeaQuery is very lightweight, all dependencies are optional (except `inherent`).
45//!
46//! ### Feature flags
47//!
48//! Macro: `derive`
49//!
50//! Async support: `thread-safe` (use `Arc` inplace of `Rc`)
51//!
52//! SQL engine: `backend-mysql`, `backend-postgres`, `backend-sqlite`
53//!
54//! Type support: `with-chrono`, `with-time`, `with-json`, `with-rust_decimal`, `with-bigdecimal`, `with-uuid`,
55//! `with-ipnetwork`, `with-mac_address`, `postgres-array`, `postgres-interval`, `postgres-vector`
56//!
57//! ## Usage
58//!
59//! Table of Content
60//!
61//! 1. Basics
62//!
63//!     1. [Iden](#iden)
64//!     1. [Expression](#expression)
65//!     1. [Condition](#condition)
66//!     1. [Statement Builders](#statement-builders)
67//!
68//! 1. Query Statement
69//!
70//!     1. [Query Select](#query-select)
71//!     1. [Query Insert](#query-insert)
72//!     1. [Query Update](#query-update)
73//!     1. [Query Delete](#query-delete)
74//!
75//! 1. Advanced
76//!     1. [Aggregate Functions](#aggregate-functions)
77//!     1. [Casting](#casting)
78//!     1. [Custom Function](#custom-function)
79//!
80//! 1. Schema Statement
81//!
82//!     1. [Table Create](#table-create)
83//!     1. [Table Alter](#table-alter)
84//!     1. [Table Drop](#table-drop)
85//!     1. [Table Rename](#table-rename)
86//!     1. [Table Truncate](#table-truncate)
87//!     1. [Foreign Key Create](#foreign-key-create)
88//!     1. [Foreign Key Drop](#foreign-key-drop)
89//!     1. [Index Create](#index-create)
90//!     1. [Index Drop](#index-drop)
91//!
92//! ### Motivation
93//!
94//! Why would you want to use a dynamic query builder?
95//!
96//! 1. Parameter bindings
97//!
98//! One of the headaches when using raw SQL is parameter binding. With SeaQuery you can:
99//!
100//! ```
101//! # use sea_query::{*, tests_cfg::*};
102//! assert_eq!(
103//!     Query::select()
104//!         .column(Glyph::Image)
105//!         .from(Glyph::Table)
106//!         .and_where(Expr::col(Glyph::Image).like("A"))
107//!         .and_where(Expr::col(Glyph::Id).is_in([1, 2, 3]))
108//!         .build(PostgresQueryBuilder),
109//!     (
110//!         r#"SELECT "image" FROM "glyph" WHERE "image" LIKE $1 AND "id" IN ($2, $3, $4)"#
111//!             .to_owned(),
112//!         Values(vec![
113//!             Value::String(Some(Box::new("A".to_owned()))),
114//!             Value::Int(Some(1)),
115//!             Value::Int(Some(2)),
116//!             Value::Int(Some(3))
117//!         ])
118//!     )
119//! );
120//! ```
121//!
122//! 2. Dynamic query
123//!
124//! You can construct the query at runtime based on user inputs:
125//!
126//! ```
127//! # use sea_query::{*, tests_cfg::*};
128//! Query::select()
129//!     .column(Char::Character)
130//!     .from(Char::Table)
131//!     .conditions(
132//!         // some runtime condition
133//!         true,
134//!         // if condition is true then add the following condition
135//!         |q| {
136//!             q.and_where(Expr::col(Char::Id).eq(1));
137//!         },
138//!         // otherwise leave it as is
139//!         |q| {},
140//!     );
141//! ```
142//!
143//! ### Iden
144//!
145//! `Iden` is a trait for identifiers used in any query statement.
146//!
147//! Commonly implemented by Enum where each Enum represents a table found in a database,
148//! and its variants include table name and column name.
149//!
150//! [`Iden::unquoted()`] must be implemented to provide a mapping between Enum variants and its
151//! corresponding string value.
152//!
153//! ```rust
154//! use sea_query::*;
155//!
156//! // For example Character table with column id, character, font_size...
157//! pub enum Character {
158//!     Table,
159//!     Id,
160//!     FontId,
161//!     FontSize,
162//! }
163//!
164//! // Mapping between Enum variant and its corresponding string value
165//! impl Iden for Character {
166//!     fn unquoted(&self, s: &mut dyn std::fmt::Write) {
167//!         write!(
168//!             s,
169//!             "{}",
170//!             match self {
171//!                 Self::Table => "character",
172//!                 Self::Id => "id",
173//!                 Self::FontId => "font_id",
174//!                 Self::FontSize => "font_size",
175//!             }
176//!         )
177//!         .unwrap();
178//!     }
179//! }
180//! ```
181//!
182//! If you're okay with running another procedural macro, you can activate
183//! the `derive` feature on the crate to save you some boilerplate.
184//! For more usage information, look at
185//! [the derive examples](https://github.com/SeaQL/sea-query/tree/master/sea-query-derive/tests/pass).
186//!
187//! ```rust
188//! #[cfg(feature = "derive")]
189//! use sea_query::Iden;
190//!
191//! // This will implement Iden exactly as shown above
192//! #[derive(Iden)]
193//! enum Character {
194//!     Table,
195//! }
196//! assert_eq!(Character::Table.to_string(), "character");
197//!
198//! // You can also derive a unit struct
199//! #[derive(Iden)]
200//! struct Glyph;
201//! assert_eq!(Glyph.to_string(), "glyph");
202//! ```
203//!
204//! ```rust
205//! #[cfg(feature = "derive")]
206//! # fn test() {
207//! use sea_query::{enum_def, Iden};
208//!
209//! #[enum_def]
210//! struct Character {
211//!     pub foo: u64,
212//! }
213//!
214//! // It generates the following along with Iden impl
215//! # let not_real = || {
216//! enum CharacterIden {
217//!     Table,
218//!     Foo,
219//! }
220//! # };
221//!
222//! assert_eq!(CharacterIden::Table.to_string(), "character");
223//! assert_eq!(CharacterIden::Foo.to_string(), "foo");
224//! # }
225//! # #[cfg(feature = "derive")]
226//! # test();
227//! ```
228//!
229//!
230//! ### Expression
231//!
232//! Use [`Expr`] constructors and [`ExprTrait`] methods
233//! to construct `SELECT`, `JOIN`, `WHERE` and `HAVING` expression in query.
234//!
235//! ```rust
236//! # use sea_query::{*, tests_cfg::*};
237//! assert_eq!(
238//!     Query::select()
239//!         .column(Char::Character)
240//!         .from(Char::Table)
241//!         .and_where(
242//!             Expr::col(Char::SizeW)
243//!                 .add(1)
244//!                 .mul(2)
245//!                 .eq(Expr::col(Char::SizeH).div(2).sub(1))
246//!         )
247//!         .and_where(
248//!             Expr::col(Char::SizeW).in_subquery(
249//!                 Query::select()
250//!                     .expr(Expr::cust_with_values("ln($1 ^ $2)", [2.4, 1.2]))
251//!                     .take()
252//!             )
253//!         )
254//!         .and_where(
255//!             Expr::col(Char::Character)
256//!                 .like("D")
257//!                 .and(Expr::col(Char::Character).like("E"))
258//!         )
259//!         .to_string(PostgresQueryBuilder),
260//!     [
261//!         r#"SELECT "character" FROM "character""#,
262//!         r#"WHERE ("size_w" + 1) * 2 = ("size_h" / 2) - 1"#,
263//!         r#"AND "size_w" IN (SELECT ln(2.4 ^ 1.2))"#,
264//!         r#"AND ("character" LIKE 'D' AND "character" LIKE 'E')"#,
265//!     ]
266//!     .join(" ")
267//! );
268//! ```
269//!
270//! ### Condition
271//!
272//! If you have complex conditions to express, you can use the [`Condition`] builder,
273//! usable for [`ConditionalStatement::cond_where`] and [`SelectStatement::cond_having`].
274//!
275//! ```
276//! # use sea_query::{*, tests_cfg::*};
277//! assert_eq!(
278//!     Query::select()
279//!         .column(Glyph::Id)
280//!         .from(Glyph::Table)
281//!         .cond_where(
282//!             Cond::any()
283//!                 .add(
284//!                     Cond::all()
285//!                         .add(Expr::col(Glyph::Aspect).is_null())
286//!                         .add(Expr::col(Glyph::Image).is_null())
287//!                 )
288//!                 .add(
289//!                     Cond::all()
290//!                         .add(Expr::col(Glyph::Aspect).is_in([3, 4]))
291//!                         .add(Expr::col(Glyph::Image).like("A%"))
292//!                 )
293//!         )
294//!         .to_string(PostgresQueryBuilder),
295//!     [
296//!         r#"SELECT "id" FROM "glyph""#,
297//!         r#"WHERE"#,
298//!         r#"("aspect" IS NULL AND "image" IS NULL)"#,
299//!         r#"OR"#,
300//!         r#"("aspect" IN (3, 4) AND "image" LIKE 'A%')"#,
301//!     ]
302//!     .join(" ")
303//! );
304//! ```
305//!
306//! There is also the [`any!`] and [`all!`] macro at your convenience:
307//!
308//! ```
309//! # use sea_query::{*, tests_cfg::*};
310//! Query::select().cond_where(any![
311//!     Expr::col(Glyph::Aspect).is_in([3, 4]),
312//!     all![
313//!         Expr::col(Glyph::Aspect).is_null(),
314//!         Expr::col(Glyph::Image).like("A%")
315//!     ]
316//! ]);
317//! ```
318//!
319//! ### Statement Builders
320//!
321//! Statements are divided into 2 categories: Query and Schema, and to be serialized into SQL
322//! with [`QueryStatementBuilder`] and [`SchemaStatementBuilder`] respectively.
323//!
324//! Schema statement has the following interface:
325//!
326//! ```rust
327//! # use sea_query::{*};
328//! # trait ExampleSchemaBuilder {
329//! fn build<T: SchemaBuilder>(&self, schema_builder: T) -> String;
330//! # }
331//! ```
332//!
333//! Query statement has the following interfaces:
334//!
335//! ```rust
336//! # use sea_query::{*};
337//! # trait ExampleQueryBuilder {
338//! fn build<T: QueryBuilder>(&self, query_builder: T) -> (String, Values);
339//!
340//! fn to_string<T: QueryBuilder>(&self, query_builder: T) -> String;
341//! # }
342//! ```
343//!
344//! `build` builds a SQL statement as string and parameters to be passed to the database driver
345//! through the binary protocol. This is the preferred way as it has less overhead and is more secure.
346//!
347//! `to_string` builds a SQL statement as string with parameters injected. This is good for testing
348//! and debugging.
349//!
350//! ### Query Select
351//!
352//! ```rust
353//! # use sea_query::{*, tests_cfg::*};
354//! let query = Query::select()
355//!     .column(Char::Character)
356//!     .column((Font::Table, Font::Name))
357//!     .from(Char::Table)
358//!     .left_join(Font::Table, Expr::col((Char::Table, Char::FontId)).equals((Font::Table, Font::Id)))
359//!     .and_where(Expr::col(Char::SizeW).is_in([3, 4]))
360//!     .and_where(Expr::col(Char::Character).like("A%"))
361//!     .to_owned();
362//!
363//! assert_eq!(
364//!     query.to_string(MysqlQueryBuilder),
365//!     r#"SELECT `character`, `font`.`name` FROM `character` LEFT JOIN `font` ON `character`.`font_id` = `font`.`id` WHERE `size_w` IN (3, 4) AND `character` LIKE 'A%'"#
366//! );
367//! assert_eq!(
368//!     query.to_string(PostgresQueryBuilder),
369//!     r#"SELECT "character", "font"."name" FROM "character" LEFT JOIN "font" ON "character"."font_id" = "font"."id" WHERE "size_w" IN (3, 4) AND "character" LIKE 'A%'"#
370//! );
371//! assert_eq!(
372//!     query.to_string(SqliteQueryBuilder),
373//!     r#"SELECT "character", "font"."name" FROM "character" LEFT JOIN "font" ON "character"."font_id" = "font"."id" WHERE "size_w" IN (3, 4) AND "character" LIKE 'A%'"#
374//! );
375//! ```
376//!
377//! ### Query Insert
378//!
379//! ```rust
380//! # use sea_query::{*, tests_cfg::*};
381//! let query = Query::insert()
382//!     .into_table(Glyph::Table)
383//!     .columns([Glyph::Aspect, Glyph::Image])
384//!     .values_panic([5.15.into(), "12A".into()])
385//!     .values_panic([4.21.into(), "123".into()])
386//!     .to_owned();
387//!
388//! assert_eq!(
389//!     query.to_string(MysqlQueryBuilder),
390//!     r#"INSERT INTO `glyph` (`aspect`, `image`) VALUES (5.15, '12A'), (4.21, '123')"#
391//! );
392//! assert_eq!(
393//!     query.to_string(PostgresQueryBuilder),
394//!     r#"INSERT INTO "glyph" ("aspect", "image") VALUES (5.15, '12A'), (4.21, '123')"#
395//! );
396//! assert_eq!(
397//!     query.to_string(SqliteQueryBuilder),
398//!     r#"INSERT INTO "glyph" ("aspect", "image") VALUES (5.15, '12A'), (4.21, '123')"#
399//! );
400//! ```
401//!
402//! ### Query Update
403//!
404//! ```rust
405//! # use sea_query::{*, tests_cfg::*};
406//! let query = Query::update()
407//!     .table(Glyph::Table)
408//!     .values([(Glyph::Aspect, 1.23.into()), (Glyph::Image, "123".into())])
409//!     .and_where(Expr::col(Glyph::Id).eq(1))
410//!     .to_owned();
411//!
412//! assert_eq!(
413//!     query.to_string(MysqlQueryBuilder),
414//!     r#"UPDATE `glyph` SET `aspect` = 1.23, `image` = '123' WHERE `id` = 1"#
415//! );
416//! assert_eq!(
417//!     query.to_string(PostgresQueryBuilder),
418//!     r#"UPDATE "glyph" SET "aspect" = 1.23, "image" = '123' WHERE "id" = 1"#
419//! );
420//! assert_eq!(
421//!     query.to_string(SqliteQueryBuilder),
422//!     r#"UPDATE "glyph" SET "aspect" = 1.23, "image" = '123' WHERE "id" = 1"#
423//! );
424//! ```
425//!
426//! ### Query Delete
427//!
428//! ```rust
429//! # use sea_query::{*, tests_cfg::*};
430//! let query = Query::delete()
431//!     .from_table(Glyph::Table)
432//!     .cond_where(
433//!         Cond::any()
434//!             .add(Expr::col(Glyph::Id).lt(1))
435//!             .add(Expr::col(Glyph::Id).gt(10)),
436//!     )
437//!     .to_owned();
438//!
439//! assert_eq!(
440//!     query.to_string(MysqlQueryBuilder),
441//!     r#"DELETE FROM `glyph` WHERE `id` < 1 OR `id` > 10"#
442//! );
443//! assert_eq!(
444//!     query.to_string(PostgresQueryBuilder),
445//!     r#"DELETE FROM "glyph" WHERE "id" < 1 OR "id" > 10"#
446//! );
447//! assert_eq!(
448//!     query.to_string(SqliteQueryBuilder),
449//!     r#"DELETE FROM "glyph" WHERE "id" < 1 OR "id" > 10"#
450//! );
451//! ```
452//!
453//! ### Aggregate Functions
454//!
455//! `max`, `min`, `sum`, `avg`, `count` etc
456//!
457//! ```rust
458//! # use sea_query::{*, tests_cfg::*};
459//! let query = Query::select()
460//!     .expr(Func::sum(Expr::col((Char::Table, Char::SizeH))))
461//!     .from(Char::Table)
462//!     .to_owned();
463//! assert_eq!(
464//!     query.to_string(MysqlQueryBuilder),
465//!     r#"SELECT SUM(`character`.`size_h`) FROM `character`"#
466//! );
467//! assert_eq!(
468//!     query.to_string(PostgresQueryBuilder),
469//!     r#"SELECT SUM("character"."size_h") FROM "character""#
470//! );
471//! assert_eq!(
472//!     query.to_string(SqliteQueryBuilder),
473//!     r#"SELECT SUM("character"."size_h") FROM "character""#
474//! );
475//! ```
476//!
477//! ### Casting
478//!
479//! ```rust
480//! # use sea_query::{*, tests_cfg::*};
481//! let query = Query::select()
482//!     .expr(Func::cast_as("hello", Alias::new("MyType")))
483//!     .to_owned();
484//!
485//! assert_eq!(
486//!     query.to_string(MysqlQueryBuilder),
487//!     r#"SELECT CAST('hello' AS MyType)"#
488//! );
489//! assert_eq!(
490//!     query.to_string(PostgresQueryBuilder),
491//!     r#"SELECT CAST('hello' AS MyType)"#
492//! );
493//! assert_eq!(
494//!     query.to_string(SqliteQueryBuilder),
495//!     r#"SELECT CAST('hello' AS MyType)"#
496//! );
497//! ```
498//!
499//! ### Custom Function
500//!
501//! ```rust
502//! # use sea_query::{*, tests_cfg::*};
503//! struct MyFunction;
504//!
505//! impl Iden for MyFunction {
506//!     fn unquoted(&self, s: &mut dyn Write) {
507//!         write!(s, "MY_FUNCTION").unwrap();
508//!     }
509//! }
510//!
511//! let query = Query::select()
512//!     .expr(Func::cust(MyFunction).arg(Expr::val("hello")))
513//!     .to_owned();
514//!
515//! assert_eq!(
516//!     query.to_string(MysqlQueryBuilder),
517//!     r#"SELECT MY_FUNCTION('hello')"#
518//! );
519//! assert_eq!(
520//!     query.to_string(PostgresQueryBuilder),
521//!     r#"SELECT MY_FUNCTION('hello')"#
522//! );
523//! assert_eq!(
524//!     query.to_string(SqliteQueryBuilder),
525//!     r#"SELECT MY_FUNCTION('hello')"#
526//! );
527//! ```
528//!
529//! ### Table Create
530//!
531//! ```rust
532//! # use sea_query::{*, tests_cfg::*};
533//! let table = Table::create()
534//!     .table(Char::Table)
535//!     .if_not_exists()
536//!     .col(ColumnDef::new(Char::Id).integer().not_null().auto_increment().primary_key())
537//!     .col(ColumnDef::new(Char::FontSize).integer().not_null())
538//!     .col(ColumnDef::new(Char::Character).string().not_null())
539//!     .col(ColumnDef::new(Char::SizeW).integer().not_null())
540//!     .col(ColumnDef::new(Char::SizeH).integer().not_null())
541//!     .col(ColumnDef::new(Char::FontId).integer().default(Value::Int(None)))
542//!     .foreign_key(
543//!         ForeignKey::create()
544//!             .name("FK_2e303c3a712662f1fc2a4d0aad6")
545//!             .from(Char::Table, Char::FontId)
546//!             .to(Font::Table, Font::Id)
547//!             .on_delete(ForeignKeyAction::Cascade)
548//!             .on_update(ForeignKeyAction::Cascade)
549//!     )
550//!     .to_owned();
551//!
552//! assert_eq!(
553//!     table.to_string(MysqlQueryBuilder),
554//!     [
555//!         r#"CREATE TABLE IF NOT EXISTS `character` ("#,
556//!             r#"`id` int NOT NULL AUTO_INCREMENT PRIMARY KEY,"#,
557//!             r#"`font_size` int NOT NULL,"#,
558//!             r#"`character` varchar(255) NOT NULL,"#,
559//!             r#"`size_w` int NOT NULL,"#,
560//!             r#"`size_h` int NOT NULL,"#,
561//!             r#"`font_id` int DEFAULT NULL,"#,
562//!             r#"CONSTRAINT `FK_2e303c3a712662f1fc2a4d0aad6`"#,
563//!                 r#"FOREIGN KEY (`font_id`) REFERENCES `font` (`id`)"#,
564//!                 r#"ON DELETE CASCADE ON UPDATE CASCADE"#,
565//!         r#")"#,
566//!     ].join(" ")
567//! );
568//! assert_eq!(
569//!     table.to_string(PostgresQueryBuilder),
570//!     [
571//!         r#"CREATE TABLE IF NOT EXISTS "character" ("#,
572//!             r#""id" serial NOT NULL PRIMARY KEY,"#,
573//!             r#""font_size" integer NOT NULL,"#,
574//!             r#""character" varchar NOT NULL,"#,
575//!             r#""size_w" integer NOT NULL,"#,
576//!             r#""size_h" integer NOT NULL,"#,
577//!             r#""font_id" integer DEFAULT NULL,"#,
578//!             r#"CONSTRAINT "FK_2e303c3a712662f1fc2a4d0aad6""#,
579//!                 r#"FOREIGN KEY ("font_id") REFERENCES "font" ("id")"#,
580//!                 r#"ON DELETE CASCADE ON UPDATE CASCADE"#,
581//!         r#")"#,
582//!     ].join(" ")
583//! );
584//! assert_eq!(
585//!     table.to_string(SqliteQueryBuilder),
586//!     [
587//!        r#"CREATE TABLE IF NOT EXISTS "character" ("#,
588//!            r#""id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,"#,
589//!            r#""font_size" integer NOT NULL,"#,
590//!            r#""character" varchar NOT NULL,"#,
591//!            r#""size_w" integer NOT NULL,"#,
592//!            r#""size_h" integer NOT NULL,"#,
593//!            r#""font_id" integer DEFAULT NULL,"#,
594//!            r#"FOREIGN KEY ("font_id") REFERENCES "font" ("id") ON DELETE CASCADE ON UPDATE CASCADE"#,
595//!        r#")"#,
596//!     ].join(" ")
597//! );
598//! ```
599//!
600//! ### Table Alter
601//!
602//! ```rust
603//! # use sea_query::{*, tests_cfg::*};
604//! let table = Table::alter()
605//!     .table(Font::Table)
606//!     .add_column(
607//!         ColumnDef::new(Alias::new("new_col"))
608//!             .integer()
609//!             .not_null()
610//!             .default(100),
611//!     )
612//!     .to_owned();
613//!
614//! assert_eq!(
615//!     table.to_string(MysqlQueryBuilder),
616//!     r#"ALTER TABLE `font` ADD COLUMN `new_col` int NOT NULL DEFAULT 100"#
617//! );
618//! assert_eq!(
619//!     table.to_string(PostgresQueryBuilder),
620//!     r#"ALTER TABLE "font" ADD COLUMN "new_col" integer NOT NULL DEFAULT 100"#
621//! );
622//! assert_eq!(
623//!     table.to_string(SqliteQueryBuilder),
624//!     r#"ALTER TABLE "font" ADD COLUMN "new_col" integer NOT NULL DEFAULT 100"#,
625//! );
626//! ```
627//!
628//! ### Table Drop
629//!
630//! ```rust
631//! # use sea_query::{*, tests_cfg::*};
632//! let table = Table::drop()
633//!     .table(Glyph::Table)
634//!     .table(Char::Table)
635//!     .to_owned();
636//!
637//! assert_eq!(
638//!     table.to_string(MysqlQueryBuilder),
639//!     r#"DROP TABLE `glyph`, `character`"#
640//! );
641//! assert_eq!(
642//!     table.to_string(PostgresQueryBuilder),
643//!     r#"DROP TABLE "glyph", "character""#
644//! );
645//! assert_eq!(
646//!     table.to_string(SqliteQueryBuilder),
647//!     r#"DROP TABLE "glyph", "character""#
648//! );
649//! ```
650//!
651//! ### Table Rename
652//!
653//! ```rust
654//! # use sea_query::{*, tests_cfg::*};
655//! let table = Table::rename()
656//!     .table(Font::Table, Alias::new("font_new"))
657//!     .to_owned();
658//!
659//! assert_eq!(
660//!     table.to_string(MysqlQueryBuilder),
661//!     r#"RENAME TABLE `font` TO `font_new`"#
662//! );
663//! assert_eq!(
664//!     table.to_string(PostgresQueryBuilder),
665//!     r#"ALTER TABLE "font" RENAME TO "font_new""#
666//! );
667//! assert_eq!(
668//!     table.to_string(SqliteQueryBuilder),
669//!     r#"ALTER TABLE "font" RENAME TO "font_new""#
670//! );
671//! ```
672//!
673//! ### Table Truncate
674//!
675//! ```rust
676//! # use sea_query::{*, tests_cfg::*};
677//! let table = Table::truncate().table(Font::Table).to_owned();
678//!
679//! assert_eq!(
680//!     table.to_string(MysqlQueryBuilder),
681//!     r#"TRUNCATE TABLE `font`"#
682//! );
683//! assert_eq!(
684//!     table.to_string(PostgresQueryBuilder),
685//!     r#"TRUNCATE TABLE "font""#
686//! );
687//! // Sqlite does not support the TRUNCATE statement
688//! ```
689//!
690//! ### Foreign Key Create
691//!
692//! ```rust
693//! # use sea_query::{*, tests_cfg::*};
694//! let foreign_key = ForeignKey::create()
695//!     .name("FK_character_font")
696//!     .from(Char::Table, Char::FontId)
697//!     .to(Font::Table, Font::Id)
698//!     .on_delete(ForeignKeyAction::Cascade)
699//!     .on_update(ForeignKeyAction::Cascade)
700//!     .to_owned();
701//!
702//! assert_eq!(
703//!     foreign_key.to_string(MysqlQueryBuilder),
704//!     [
705//!         r#"ALTER TABLE `character`"#,
706//!         r#"ADD CONSTRAINT `FK_character_font`"#,
707//!         r#"FOREIGN KEY (`font_id`) REFERENCES `font` (`id`)"#,
708//!         r#"ON DELETE CASCADE ON UPDATE CASCADE"#,
709//!     ]
710//!     .join(" ")
711//! );
712//! assert_eq!(
713//!     foreign_key.to_string(PostgresQueryBuilder),
714//!     [
715//!         r#"ALTER TABLE "character" ADD CONSTRAINT "FK_character_font""#,
716//!         r#"FOREIGN KEY ("font_id") REFERENCES "font" ("id")"#,
717//!         r#"ON DELETE CASCADE ON UPDATE CASCADE"#,
718//!     ]
719//!     .join(" ")
720//! );
721//! // Sqlite does not support modification of foreign key constraints to existing tables
722//! ```
723//!
724//! ### Foreign Key Drop
725//!
726//! ```rust
727//! # use sea_query::{*, tests_cfg::*};
728//! let foreign_key = ForeignKey::drop()
729//!     .name("FK_character_font")
730//!     .table(Char::Table)
731//!     .to_owned();
732//!
733//! assert_eq!(
734//!     foreign_key.to_string(MysqlQueryBuilder),
735//!     r#"ALTER TABLE `character` DROP FOREIGN KEY `FK_character_font`"#
736//! );
737//! assert_eq!(
738//!     foreign_key.to_string(PostgresQueryBuilder),
739//!     r#"ALTER TABLE "character" DROP CONSTRAINT "FK_character_font""#
740//! );
741//! // Sqlite does not support modification of foreign key constraints to existing tables
742//! ```
743//!
744//! ### Index Create
745//!
746//! ```rust
747//! # use sea_query::{*, tests_cfg::*};
748//! let index = Index::create()
749//!     .name("idx-glyph-aspect")
750//!     .table(Glyph::Table)
751//!     .col(Glyph::Aspect)
752//!     .to_owned();
753//!
754//! assert_eq!(
755//!     index.to_string(MysqlQueryBuilder),
756//!     r#"CREATE INDEX `idx-glyph-aspect` ON `glyph` (`aspect`)"#
757//! );
758//! assert_eq!(
759//!     index.to_string(PostgresQueryBuilder),
760//!     r#"CREATE INDEX "idx-glyph-aspect" ON "glyph" ("aspect")"#
761//! );
762//! assert_eq!(
763//!     index.to_string(SqliteQueryBuilder),
764//!     r#"CREATE INDEX "idx-glyph-aspect" ON "glyph" ("aspect")"#
765//! );
766//! ```
767//!
768//! ### Index Drop
769//!
770//! ```rust
771//! # use sea_query::{*, tests_cfg::*};
772//! let index = Index::drop()
773//!     .name("idx-glyph-aspect")
774//!     .table(Glyph::Table)
775//!     .to_owned();
776//!
777//! assert_eq!(
778//!     index.to_string(MysqlQueryBuilder),
779//!     r#"DROP INDEX `idx-glyph-aspect` ON `glyph`"#
780//! );
781//! assert_eq!(
782//!     index.to_string(PostgresQueryBuilder),
783//!     r#"DROP INDEX "idx-glyph-aspect""#
784//! );
785//! assert_eq!(
786//!     index.to_string(SqliteQueryBuilder),
787//!     r#"DROP INDEX "idx-glyph-aspect""#
788//! );
789//! ```
790//!
791//! ## License
792//!
793//! Licensed under either of
794//!
795//! -   Apache License, Version 2.0
796//!     ([LICENSE-APACHE](LICENSE-APACHE) or <http://www.apache.org/licenses/LICENSE-2.0>)
797//! -   MIT license
798//!     ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
799//!
800//! at your option.
801//!
802//! ## Contribution
803//!
804//! Unless you explicitly state otherwise, any contribution intentionally submitted
805//! for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
806//! dual licensed as above, without any additional terms or conditions.
807//!
808//! SeaQuery is a community driven project. We welcome you to participate, contribute and together build for Rust's future.
809//!
810//! A big shout out to our contributors:
811//!
812//! [![Contributors](https://opencollective.com/sea-query/contributors.svg?width=1000&button=false)](https://github.com/SeaQL/sea-query/graphs/contributors)
813#![doc(
814    html_logo_url = "https://raw.githubusercontent.com/SeaQL/sea-query/master/docs/SeaQL icon dark.png"
815)]
816
817pub mod backend;
818pub mod error;
819pub mod expr;
820pub mod extension;
821pub mod foreign_key;
822pub mod func;
823pub mod index;
824pub mod prepare;
825pub mod query;
826pub mod schema;
827pub mod table;
828pub mod token;
829pub mod types;
830pub mod value;
831
832#[doc(hidden)]
833#[cfg(feature = "tests-cfg")]
834pub mod tests_cfg;
835
836pub use backend::*;
837pub use expr::*;
838pub use foreign_key::*;
839pub use func::*;
840pub use index::*;
841pub use prepare::*;
842pub use query::*;
843pub use schema::*;
844pub use table::*;
845pub use token::*;
846pub use types::*;
847pub use value::*;
848
849#[cfg(feature = "derive")]
850pub use sea_query_derive::{enum_def, Iden, IdenStatic};
851
852#[cfg(all(feature = "attr", not(feature = "derive")))]
853pub use sea_query_derive::enum_def;