derive_sql_statement/lib.rs
1//! Procedural macro to automatically generate SQL statements traits `TableStatement`, `SelectStatement`, `InsertStatement`, `DeleteStatement` for the
2//! provided struct as well as conversion to SQL parameters and from SQL rows.
3//!
4//! # How to use
5//!
6//! You write:
7//! ```rust
8//! # use derive_sql::*;
9//! #[derive(derive_sql::DeriveSqlStatement)]
10//! pub struct Person {
11//! name: String,
12//! age: u32,
13//! }
14//! ```
15//!
16//! And you can use:
17//! ```rust
18//! # use derive_sql::*;
19//! # #[derive(DeriveSqlStatement)]
20//! # pub struct Person {
21//! # name: String,
22//! # age: u32,
23//! # }
24//! use derive_sql::structs::*;
25//!
26//! fn handle<Con, Row>(s: &mut Con)
27//! where Con: traits::Connection<Row>,
28//! Row: traits::Row,
29//! {
30//! use derive_sql::traits::{Table, SelectV2, Insert, Delete, Update};
31//! let db = SqlPerson::default();
32//!
33//! // initialise
34//! db.create(s).unwrap();
35//!
36//! // Insert entries
37//! db.insert(s, &Person {name: "Abi".to_string(), age: 31 }).unwrap();
38//! db.insert(s, &Person {name: "Bert".to_string(), age: 32 }).unwrap();
39//! db.insert(s, &Person {name: "Charlie".to_string(), age: 33 }).unwrap();
40//!
41//! // Query
42//! let persons: Vec<Person> = db.select_with_filter(s, &Field::from("age").eq(32)).unwrap();
43//! assert!(persons[0].name.eq("Bert"));
44//!
45//! // Update
46//! db.update_with_filter(s, &Field::from("name").eq("Abi"), &Person { name: "Abi".to_string(), age: 32 }).unwrap();
47//!
48//! // Delete
49//! db.delete_with_filter(s, &Field::from("name").eq("Abi")).unwrap();
50//!
51//! // Clear the table
52//! db.drop(s).unwrap();
53//! }
54//!
55//! let pool = mysql::Pool::new("mysql://test@localhost/simpledb").unwrap();
56//! let mut connection = pool.get_conn().unwrap();
57//! handle(&mut connection);
58//! ```
59//!
60//! # Container attributes:
61//! - `#[derive_sqlite(ident = ...)]` overwrite the name of the wrapper from `Sql{class}`;
62//! - `#[derive_sqlite(table_name = "...")]` specify the name of the table (default to the container name in lower case);
63//! - `#[derive_sqlite(read_only = true/false)]` specify whether to implement read/write (ie table, select, insert, update, delete, to params conversion and from row conversion)
64//! or read only statements (ie select and from row conversion)
65//!
66//! # Field attributes:
67//! - `#[derive_sqlite(is_primary_key = true)]` nominate that one of the field is a primary key. Only one primary key can be specified.
68//! primary key fields are unique in the table. Primary key can NOT be a String - the following will not compile:
69//!
70//! ```compile_fail
71//! # use derive_sql::*;
72//! # use derive_sql_mysql::DeriveMysql;
73//! #[derive(DeriveMysql)]
74//! pub struct Person {
75//! #[derive_sqlite(is_primary_key = true)]
76//! name: String,
77//! age: u32,
78//! }
79//! ```
80//!
81
82mod statement;
83
84use attribute_derive::{Attribute};
85
86#[derive(Attribute)]
87#[attribute(ident = derive_sql)]
88struct Attrs {
89 ident: Option<syn::Ident>,
90 table_name: Option<String>,
91 read_only: bool,
92}
93
94#[proc_macro_derive(DeriveSqlStatement, attributes(derive_sql, derive_sqlite))]
95pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
96 syn::parse(input)
97 .and_then(|ast: syn::DeriveInput| {
98 Ok(statement::Statement::try_from(&ast)?.generate()?)
99 })
100 .unwrap_or_else(|e| e.into_compile_error())
101 .into()
102}
103