easy_sqlx_core/sql/schema/
index.rs1use easy_sqlx_utils::{ternary, value_parser::parse_next};
2use quote::{quote, ToTokens};
3use syn::{parse::Parse, punctuated::Punctuated, token::Comma, Error, Ident, LitStr, Token};
4
5#[derive(Clone, Debug, Default)]
6pub struct Index {
7 pub columns: Vec<String>,
8 pub name: String,
9 pub unique: bool,
11}
12
13impl Index {
14 pub fn is_name_equal(&self, idx: &Index) -> bool {
15 self.name.to_uppercase() == idx.name.to_uppercase()
16 }
17
18 pub fn is_columns_equal(&self, idx: &Index) -> bool {
19 idx.columns == self.columns
20 }
21
22 pub fn get_name(&self, table_name: &String) -> (String, bool) {
23 let type_name = ternary!(self.unique, "uqe", "idx");
24 if self.name.is_empty() {
25 let name = self.columns.join("_");
26 (format!("{table_name}_{type_name}_{name}"), false)
27 } else {
28 (format!("{table_name}_{type_name}_{}", self.name), true)
29 }
30 }
31
32 pub fn get_name_with_index(&self, table_name: &String, index: i32) -> (String, bool) {
33 let type_name = ternary!(self.unique, "uqe", "idx");
34 if self.name.is_empty() {
35 let name = self.columns.join("_");
36 (format!("{table_name}_{type_name}_{index}_{name}"), false)
38 } else {
39 (format!("{table_name}_{type_name}_{}", self.name), true)
41 }
42 }
43
44 }
55
56impl ToTokens for Index {
57 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
58 let name = self.name.clone(); let unique = self.unique;
60
61 let cols = self.columns.clone();
62 quote! {
63 easy_sqlx_core::sql::schema::index::Index {
64 columns: [#(#cols.to_string()), *].to_vec(),
65 name: #name.to_string(),
66 unique: #unique,
67 ..Default::default()
68 }
69 }
70 .to_tokens(tokens);
71 }
72}
73
74impl Parse for Index {
75 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
76 const EXPECTED_ATTRIBUTE: &str =
77 "unexpected attribute, expected any of: name, columns[], unique";
78
79 let mut index = Index::default();
80 while !input.is_empty() {
81 let ident = input.parse::<Ident>().map_err(|error| {
82 Error::new(error.span(), format!("{EXPECTED_ATTRIBUTE}, {error}"))
83 })?;
84 let attribute = &*ident.to_string();
85
86 match attribute {
87 "name" => {
88 index.name = parse_next(input, || input.parse::<LitStr>())
89 .map_err(|err| {
90 Error::new(
91 err.span(),
92 format!("attribute {attribute} parse error, {err}"),
93 )
94 })?
95 .value();
96 }
97 "columns" => {
98 let columns;
99 syn::parenthesized!(columns in input); let scopes = Punctuated::<LitStr, Comma>::parse_terminated(&columns)?
102 .iter()
103 .map(LitStr::value)
104 .collect::<Vec<_>>();
105
106 index.columns = scopes;
107 }
108 "unique" => {
109 index.unique = true;
110 }
111 _ => {
112 return Err(Error::new(ident.span(), EXPECTED_ATTRIBUTE));
113 }
114 }
115
116 if !input.is_empty() {
117 input.parse::<Token![,]>()?;
118 }
119 }
120 Ok(index)
122 }
123}