derive_sql_sqlite/
lib.rs

1//! Procedural macro to automatically generate an `Sqlable` trait for the 
2//! provided struct that is compatible with an SQLite database.
3//!
4//! # How to use
5//! 
6//! You write:
7//! ```rust
8//! # use derive_sql::*;
9//! # use derive_sql_sqlite::DeriveSqlite;
10//! #[derive(DeriveSqlite)]
11//! pub struct Person {
12//!   name: String,
13//!   age: u32,
14//! }
15//! ```
16//! 
17//! And you can use:
18//! ```rust
19//! # use derive_sql::*;
20//! # use derive_sql_sqlite::DeriveSqlite;
21//! # #[derive(DeriveSqlite)]
22//! # pub struct Person {
23//! #   name: String,
24//! #   age: u32,
25//! # }
26//!
27//! let connection = rusqlite::Connection::open_in_memory().unwrap();
28//! let mut db: PersonSqlite<_> = connection.into();
29//!
30//! // initialise
31//! db.create_table().unwrap();
32//!
33//! // Insert entries
34//! db.insert(Person {name: "Abi".to_string(), age: 31 }).unwrap();
35//! db.insert(Person {name: "Bert".to_string(), age: 32 }).unwrap();
36//! db.insert(Person {name: "Charlie".to_string(), age: 33 }).unwrap();
37//! 
38//! // Query
39//! let persons: Vec<Person> = db.select(Box::new(SimpleFilter::try_from(("age", 32)).unwrap())).unwrap();
40//! assert!(persons[0].name.eq("Bert"));
41//!
42//! // Update
43//! db.update(Box::new(SimpleFilter::try_from(("name", "Abi")).unwrap()), Person { name: "Abi".to_string(), age: 32 }).unwrap();
44//!
45//! // Delete
46//! db.delete(Box::new(SimpleFilter::try_from(("name", "Abi")).unwrap())).unwrap();
47//!
48//! // Clear the table
49//! db.delete_table().unwrap();
50//! ```
51//!
52//! # Container attributes:
53//! - `#[derive_sqlite(ident = ...)]` overwrite the name of the `rusqlite` wrapper from `{class}Sqlite`;
54//! - `#[derive_sqlite(table_name = "...")]` specify the name of the table (default to the container name in lower case);
55//!
56//! # Field attributes:
57//! - `#[derive_sqlite(is_primary_key = true)]` nominate that one of the field is a primary key. Only one primary key can be specified.
58//! primary key fields are unique in the table.
59//! - `#[derive_sqlite(on_insert = ...)]` nominate a function of the type `fn() -> {type}` with `{type}` corresponding to the type of the 
60//! field. The function is called when the item is inserted and the value returned by the function is assigned to the field before the
61//! item is inserted. Typical use is to assign a creation date.
62//! - `#[derive_sqlite(on_update = ...)]` nominate a function of the type `fn() -> {type}` with `{type}` corresponding to the type of the 
63//! field. The function is called when the item is updated and the value returned by the function is assigned to the field before the
64//! item is updated. Typical use is to assign a last modified date.
65//!
66
67mod sqlite;
68
69use attribute_derive::{Attribute};
70
71#[derive(Attribute)]
72#[attribute(ident = derive_sqlite)]
73struct Attrs {
74  ident: Option<syn::Ident>,
75  table_name: Option<String>,
76}
77
78#[proc_macro_derive(DeriveSqlite, attributes(derive_sqlite))]
79pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
80  syn::parse(input)
81  .and_then(|ast: syn::DeriveInput| {
82    Ok(sqlite::Sqlite::try_from(&ast)?.generate()?)
83  })
84  .unwrap_or_else(|e| e.into_compile_error())
85  .into()
86}
87