Skip to content

Commit 8e23a53

Browse files
the2pizzaHandy-caT
andauthored
Refactor SelectQueryBuilder (#53)
Co-authored-by: Handy-caT <[email protected]>
1 parent 6abdbca commit 8e23a53

File tree

13 files changed

+296
-446
lines changed

13 files changed

+296
-446
lines changed

codegen/src/name_generator.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ impl WorktableNameGenerator {
3636
)
3737
}
3838

39+
pub fn get_column_range_type_ident(&self) -> Ident {
40+
Ident::new(
41+
format!("{}ColumnRange", self.name).as_str(),
42+
Span::mixed_site(),
43+
)
44+
}
45+
3946
pub fn get_work_table_ident(&self) -> Ident {
4047
Ident::new(
4148
format!("{}WorkTable", self.name).as_str(),

codegen/src/worktable/generator/queries/select.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,15 @@ impl Generator {
2020
fn gen_select_all(&mut self) -> TokenStream {
2121
let name_generator = WorktableNameGenerator::from_table_name(self.name.to_string());
2222
let row_ident = name_generator.get_row_type_ident();
23+
let column_range_type = name_generator.get_column_range_type_ident();
2324

2425
quote! {
25-
pub fn select_all<'a>(&'a self) -> SelectQueryBuilder<'a, #row_ident, Self> {
26-
SelectQueryBuilder::new(&self)
26+
pub fn select_all(&self) -> SelectQueryBuilder<#row_ident, impl DoubleEndedIterator<Item = #row_ident> + '_ + Sized, #column_range_type> {
27+
let iter = self.0.pk_map
28+
.iter()
29+
.filter_map(|(_, link)| self.0.data.select(*link).ok());
30+
31+
SelectQueryBuilder::new(iter)
2732
}
2833
}
2934
}

codegen/src/worktable/generator/table/index_fns.rs

Lines changed: 11 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ impl Generator {
1212
let name_generator = WorktableNameGenerator::from_table_name(self.name.to_string());
1313
let ident = name_generator.get_work_table_ident();
1414
let row_ident = name_generator.get_row_type_ident();
15+
let column_range_type = name_generator.get_column_range_type_ident();
1516

1617
let fn_defs = self
1718
.columns
@@ -26,6 +27,7 @@ impl Generator {
2627
idx,
2728
&self.columns.columns_map,
2829
row_ident.clone(),
30+
&column_range_type,
2931
)
3032
}
3133
})
@@ -63,6 +65,7 @@ impl Generator {
6365
idx: &Index,
6466
columns_map: &HashMap<Ident, TokenStream>,
6567
row_ident: Ident,
68+
column_range_type: &Ident,
6669
) -> syn::Result<TokenStream> {
6770
let type_ = columns_map
6871
.get(i)
@@ -71,139 +74,14 @@ impl Generator {
7174
let field_ident = &idx.name;
7275

7376
Ok(quote! {
74-
pub fn #fn_name(&self, by: #type_) -> core::result::Result<SelectResult<#row_ident, Self>, WorkTableError> {
75-
let rows = {
76-
self.0.indexes.#field_ident.get(&by)
77-
.map(|kv| *kv.1)
78-
.collect::<Vec<_>>()
79-
}.iter().map(|link| {
80-
self.0.data.select(*link).map_err(WorkTableError::PagesError)
81-
})
82-
.collect::<Result<Vec<_>, _>>()?;
83-
core::result::Result::Ok(SelectResult::<#row_ident, Self>::new(rows))
84-
}
85-
})
86-
}
87-
88-
pub fn gen_select_where_fns(&self) -> syn::Result<TokenStream> {
89-
let name_generator = WorktableNameGenerator::from_table_name(self.name.to_string());
90-
let ident = name_generator.get_work_table_ident();
91-
let row_ident = name_generator.get_row_type_ident();
92-
93-
let fn_defs = self
94-
.columns
95-
.indexes
96-
.iter()
97-
.map(|(i, idx)| {
98-
let type_ = self
99-
.columns
100-
.columns_map
101-
.get(i)
102-
.ok_or(syn::Error::new(i.span(), "Row not found"))?;
103-
if type_.to_string() == "String" {
104-
return Ok(quote! {});
105-
}
106-
if idx.is_unique {
107-
Self::gen_unique_select_where_fn(
108-
i,
109-
idx,
110-
&self.columns.columns_map,
111-
row_ident.clone(),
112-
)
113-
} else {
114-
Self::gen_non_unique_select_where_fn(
115-
i,
116-
idx,
117-
&self.columns.columns_map,
118-
row_ident.clone(),
119-
)
120-
}
121-
})
122-
.collect::<Result<Vec<_>, syn::Error>>()?;
123-
124-
Ok(quote! {
125-
impl #ident {
126-
#(#fn_defs)*
127-
}
128-
})
129-
}
130-
131-
fn gen_unique_select_where_fn(
132-
i: &Ident,
133-
idx: &Index,
134-
columns_map: &HashMap<Ident, TokenStream>,
135-
row_ident: Ident,
136-
) -> syn::Result<TokenStream> {
137-
let type_ = columns_map
138-
.get(i)
139-
.ok_or(syn::Error::new(i.span(), "Row not found"))?;
140-
let fn_name = Ident::new(format!("select_where_{i}").as_str(), Span::mixed_site());
141-
let field_ident = &idx.name;
142-
143-
Ok(quote! {
144-
pub fn #fn_name(&self, range: impl std::ops::RangeBounds<#type_>) -> Option<Vec<#row_ident>> {
145-
146-
let start = match range.start_bound() {
147-
std::ops::Bound::Included(val) => *val,
148-
std::ops::Bound::Excluded(val) => *val + 1,
149-
std::ops::Bound::Unbounded => #type_::MIN,
150-
};
151-
152-
let end = match range.end_bound() {
153-
std::ops::Bound::Included(val) => *val,
154-
std::ops::Bound::Excluded(val) => *val - 1,
155-
std::ops::Bound::Unbounded => #type_::MAX,
156-
};
157-
158-
let rows = self.0.indexes.#field_ident
159-
.range::<#type_, _>((std::ops::Bound::Included(&start), std::ops::Bound::Included(&end)))
160-
.map(|(_key, link)| self.0.data.select(*link))
161-
.collect::<Result<Vec<_>, _>>()
162-
.ok()?;
163-
164-
if !rows.is_empty() {
165-
Some(rows)
166-
} else {
167-
None
168-
}
169-
}
170-
})
171-
}
172-
173-
fn gen_non_unique_select_where_fn(
174-
i: &Ident,
175-
idx: &Index,
176-
columns_map: &HashMap<Ident, TokenStream>,
177-
row_ident: Ident,
178-
) -> syn::Result<TokenStream> {
179-
let type_ = columns_map
180-
.get(i)
181-
.ok_or(syn::Error::new(i.span(), "Row not found"))?;
182-
let fn_name = Ident::new(format!("select_where_{i}").as_str(), Span::mixed_site());
183-
let field_ident = &idx.name;
184-
185-
Ok(quote! {
186-
pub fn #fn_name(&self, range: impl std::ops::RangeBounds<#type_>) -> core::result::Result<SelectResult<#row_ident, Self>, WorkTableError> {
187-
188-
let start = match range.start_bound() {
189-
std::ops::Bound::Included(val) => *val,
190-
std::ops::Bound::Excluded(val) => *val + 1,
191-
std::ops::Bound::Unbounded => #type_::MIN,
192-
};
193-
194-
let end = match range.end_bound() {
195-
std::ops::Bound::Included(val) => *val,
196-
std::ops::Bound::Excluded(val) => *val - 1,
197-
std::ops::Bound::Unbounded => #type_::MAX,
198-
};
199-
200-
let rows = self.0.indexes.#field_ident
201-
.range((std::ops::Bound::Included(&start), std::ops::Bound::Included(&end)))
202-
.map(|(_key, link)| { self.0.data.select(*link).map_err(WorkTableError::PagesError)
203-
}).collect::<Result<Vec<_>, _>>()?;
204-
205-
core::result::Result::Ok(SelectResult::<#row_ident, Self>::new(rows))
206-
77+
pub fn #fn_name(&self, by: #type_) -> SelectQueryBuilder<#row_ident, impl DoubleEndedIterator<Item = #row_ident> + '_, #column_range_type> {
78+
let rows: Vec<#row_ident> = self.0.indexes.#field_ident
79+
.get(&by)
80+
.into_iter()
81+
.filter_map(|(_, link)| self.0.data.select(*link).ok())
82+
.collect();
83+
84+
SelectQueryBuilder::new(rows.into_iter())
20785
}
20886
})
20987
}

codegen/src/worktable/generator/table/mod.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,17 @@ impl Generator {
1515
let default = self.gen_table_default();
1616
let impl_ = self.gen_table_impl();
1717
let index_fns = self.gen_table_index_fns()?;
18-
let select_executor_impl = self.gen_table_select_executor_impl();
19-
let select_result_executor_impl = self.gen_table_select_result_executor_impl();
20-
21-
let range = self.gen_select_where_fns()?;
18+
let select_query_executor_impl = self.gen_table_select_query_executor_impl();
19+
let column_range_type = self.gen_table_column_range_type();
2220

2321
Ok(quote! {
2422
#page_size_consts
2523
#type_
2624
#default
2725
#impl_
2826
#index_fns
29-
#select_executor_impl
30-
#select_result_executor_impl
31-
32-
#range
27+
#select_query_executor_impl
28+
#column_range_type
3329
})
3430
}
3531

0 commit comments

Comments
 (0)