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