easy_sqlx_core/sql/schema/
index.rs

1use 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 regular: bool,
10    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            // 自动生成的索引名称,可以添加序号
37            (format!("{table_name}_{type_name}_{index}_{name}"), false)
38        } else {
39            // 手动设置名称的索引不允许添加序号
40            (format!("{table_name}_{type_name}_{}", self.name), true)
41        }
42    }
43
44    // pub fn generate_name(&mut self) {
45    //     if self.name.is_empty() {
46    //         let mut name = self.columns.join("_");
47    //         name.push_str("_index");
48    //         self.name = name.to_owned();
49    //     }
50    // }
51    // pub fn get_name(self) -> String {
52    //     return self.name.clone().unwrap();
53    // }
54}
55
56impl ToTokens for Index {
57    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
58        let name = self.name.clone(); // .unwrap_or("".to_string());
59        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); // () 括住 索引字段列表
100
101                    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        // index.generate_name();
121        Ok(index)
122    }
123}