barrel/lib.rs
1//! Powerful schema migration builder, that let's you write your SQL
2//! migrations in Rust.
3//!
4//! `barrel` makes writing migrations for different databases as easy
5//! as possible. It provides you with a common API over SQL, with
6//! certain features only provided for database specific
7//! implementations. This way you can focus on your Rust code, and
8//! stop worrying about SQL.
9//!
10//! `barrel` has three primary models: the
11//! [Migration](migration/struct.Migration.html) which represents all
12//! changes and changes made on a database level, the
13//! [Table](table/struct.Table.html) and the
14//! [Type](types/struct.Type.html).
15//!
16//! When creating or altering tables a lambda which exposes `&mut
17//! Table` is provided for initialisation. Adding columns is then as
18//! easy as calling `add_column(...)` on the table.
19//!
20//! Each column is statically typed and some types require some
21//! metadata in order to compile the migration (for example
22//! `Varchar(255)`). You can also provide default types and override
23//! encodings, nullability or uniqueness of columns. Some checks are
24//! performed at compile-time however most things (including) correct
25//! default values) are only checked at runtime.
26//!
27//! **Note** Since version `0.3.0` it is required to provide a
28//! database backend in order to compile `barrel`.
29//!
30//! The following code is a simple example of how to get going with
31//! `barrel`
32//!
33//! ```rust
34//! use barrel::{types, Migration};
35//!
36//! fn main() {
37//! let mut m = Migration::new();
38//! m.create_table("users", |t| {
39//! t.add_column("name", types::varchar(255));
40//! t.add_column("age", types::integer());
41//! t.add_column("owns_plushy_sharks", types::boolean());
42//! });
43//! }
44//! ```
45//!
46//! `barrel` also supports more advanced types, such as `foreign(...)`
47//! and `array(...)` however currently doesn't support nested Array
48//! types on foreign keys (such as `array(array(foreign(...)))`). Each
49//! column addition returns a Column object which can then be used to
50//! provide further configuration.
51//!
52//! To generate SQL strings you have two options. If you just want to
53//! run the migration yourself simply run `Migration::exec()` where
54//! you provide a generic `SqlGenerator` type according to your
55//! database backend
56//!
57//! ```rust
58//! # #[cfg(feature = "pg")]
59//! # use barrel::backend::Pg;
60//! # use barrel::Migration;
61//! # let mut m = Migration::new();
62//! // Example for pgsql
63//! # #[cfg(feature = "pg")]
64//! m.make::<Pg>();
65//! ```
66//!
67//! Alternatively, if you're a library developer and you want to more
68//! easily embed `barrel` into your library you can simply implement
69//! the `DatabaseExecutor` trait for a type of yours that knows how to
70//! execute SQL. Running a migration with `barrel` is then super
71//! easy.
72//!
73//! ```rust
74//! use barrel::connectors::SqlRunner;
75//! # use barrel::Migration;
76//! # #[cfg(feature = "pg")]
77//! # use barrel::backend::Pg;
78//!
79//! struct MyRunner;
80//! impl SqlRunner for MyRunner {
81//! fn execute<S: Into<String>>(&mut self, sql: S) {
82//! # let s: String = sql.into();
83//! // ...
84//! }
85//! }
86//!
87//! # let mut m = Migration::new();
88//! # let mut executor = MyRunner;
89//! # #[cfg(feature = "pg")]
90//! m.execute::<Pg, _>(&mut executor);
91//! ```
92//!
93//! In this case `executor` is your provided type which implements the
94//! required trait. You can read more about this in the
95//! [connectors](connectors/index.html) module docs.
96//!
97//! If you find database-specific features or documentation lacking,
98//! don't hesitate to open an issue/PR about it.
99
100#[cfg(feature = "diesel")]
101pub mod integrations;
102#[cfg(feature = "diesel")]
103pub use integrations::*;
104
105pub mod backend;
106pub mod connectors;
107pub mod functions;
108pub mod migration;
109pub mod table;
110pub mod types;
111
112pub use backend::SqlVariant;
113pub use migration::Migration;
114pub use table::{Table, TableMeta};
115
116#[cfg(test)]
117mod tests;
118
119use std::rc::Rc;
120
121/// An enum set that represents a single change on a table
122#[derive(Clone)]
123pub enum TableChange {
124 /// Add a column of a name and type
125 AddColumn(String, types::Type),
126
127 /// Change an existing column
128 ChangeColumn(String, types::Type, Rc<dyn Fn(&mut types::Type)>),
129
130 /// Simply rename a column
131 RenameColumn(String, String),
132
133 /// Remove a column
134 DropColumn(String),
135
136 /// Add some custom SQL if all else fails
137 CustomLine(String),
138}
139
140/// An enum set that represents a single change on a database
141#[derive(Clone)]
142pub enum DatabaseChange {
143 /// Create a new table
144 CreateTable(Table, Rc<dyn Fn(&mut Table)>),
145
146 /// Create a new table *only* if it doesn't exist yet
147 CreateTableIfNotExists(Table, Rc<dyn Fn(&mut Table)>),
148
149 /// Change fields on an existing table
150 ChangeTable(Table, Rc<dyn Fn(&mut Table)>),
151
152 /// Rename a table
153 RenameTable(String, String),
154
155 /// Drop an existing table
156 DropTable(String),
157
158 /// Only drop a table if it exists
159 DropTableIfExists(String),
160
161 /// Add some custom SQL if all else fails
162 CustomLine(String),
163}
164
165/// An enum set that represents operations done with and on indices
166#[derive(Clone)]
167pub enum IndexChange {
168 /// Add a multi-column index
169 AddIndex {
170 index: String,
171 table: String,
172 columns: types::Type, // Should always be a `Index` type
173 },
174
175 AddPartialIndex {
176 index: String,
177 table: String,
178 columns: types::Type, // Should always be a `Index` type
179 conditions: String,
180 },
181
182 /// Remove a multi-column index
183 RemoveIndex(String, String),
184}
185
186/// An enum set that represents operations done with and on constraints
187#[derive(Clone)]
188pub enum ConstraintChange {
189 /// Add a new constraint
190 AddConstraint {
191 index: String,
192 columns: types::Type, // Should always be a `Constraint` type
193 },
194}
195
196/// An enum set that represents operations done with and on foreign keys
197#[derive(Clone)]
198pub enum ForeignKeyChange {
199 /// Add a foreign key
200 AddForeignKey {
201 columns: Vec<String>,
202 table: String,
203 relation_columns: Vec<String>,
204 },
205}
206
207/// An enum set that represents operations done to the primary key
208#[derive(Clone)]
209pub enum PrimaryKeyChange {
210 /// Adds a primary key to the table
211 AddPrimaryKey(Vec<String>),
212}