Skip to content

Commit bd368b4

Browse files
authored
Add range selects logic (#156)
1 parent 9a54904 commit bd368b4

9 files changed

Lines changed: 694 additions & 12 deletions

File tree

codegen/src/generators/in_memory/table/impls.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ impl InMemoryGenerator {
1313
let persisted_impl = self.gen_table_new_fn();
1414
let name_fn = self.gen_table_name_fn();
1515
let select_fn = self.gen_table_select_fn();
16+
let select_range_fn = self.gen_table_select_range_fn();
1617
let insert_fn = self.gen_table_insert_fn();
1718
let reinsert_fn = self.gen_table_reinsert_fn();
1819
let upsert_fn = self.gen_table_upsert_fn();
@@ -28,6 +29,7 @@ impl InMemoryGenerator {
2829
impl #ident {
2930
#name_fn
3031
#select_fn
32+
#select_range_fn
3133
#insert_fn
3234
#reinsert_fn
3335
#upsert_fn
@@ -74,6 +76,36 @@ impl InMemoryGenerator {
7476
}
7577
}
7678

79+
fn gen_table_select_range_fn(&self) -> TokenStream {
80+
let name_generator = WorktableNameGenerator::from_table_name(self.name.to_string());
81+
let row_type = name_generator.get_row_type_ident();
82+
let primary_key_type = name_generator.get_primary_key_type_ident();
83+
let column_range_type = name_generator.get_column_range_type_ident();
84+
let row_fields_ident = name_generator.get_row_fields_enum_ident();
85+
86+
quote! {
87+
pub fn select_by_pk_range<R, Pk>(&self, range: R) -> SelectQueryBuilder<#row_type,
88+
impl DoubleEndedIterator<Item = #row_type> + '_,
89+
#column_range_type,
90+
#row_fields_ident>
91+
where
92+
#primary_key_type: From<Pk>,
93+
R: std::ops::RangeBounds<Pk>,
94+
Pk: Clone,
95+
{
96+
let converted_range = (
97+
range.start_bound().map(|v| #primary_key_type::from(v.clone())),
98+
range.end_bound().map(|v| #primary_key_type::from(v.clone())),
99+
);
100+
let rows = self.0.primary_index.pk_map
101+
.range(converted_range)
102+
.filter_map(|(_, link)| self.0.data.select_non_ghosted(link.0).ok());
103+
104+
SelectQueryBuilder::new(rows)
105+
}
106+
}
107+
}
108+
77109
fn gen_table_insert_fn(&self) -> TokenStream {
78110
let name_generator = WorktableNameGenerator::from_table_name(self.name.to_string());
79111
let row_type = name_generator.get_row_type_ident();

codegen/src/generators/in_memory/table/index_fns.rs

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ impl InMemoryGenerator {
2020
.indexes
2121
.iter()
2222
.map(|(i, idx)| {
23-
if idx.is_unique {
24-
Self::gen_unique_index_fn(i, idx, &self.columns.columns_map, row_ident.clone())
23+
let point_fn = if idx.is_unique {
24+
Self::gen_unique_index_fn(i, idx, &self.columns.columns_map, row_ident.clone())?
2525
} else {
2626
Self::gen_non_unique_index_fn(
2727
i,
@@ -30,8 +30,19 @@ impl InMemoryGenerator {
3030
row_ident.clone(),
3131
&column_range_type,
3232
&row_fields_ident,
33-
)
34-
}
33+
)?
34+
};
35+
36+
let range_fn = Self::gen_range_index_fn(
37+
i,
38+
idx,
39+
&self.columns.columns_map,
40+
row_ident.clone(),
41+
&column_range_type,
42+
&row_fields_ident,
43+
)?;
44+
45+
Ok(quote! { #point_fn #range_fn })
3546
})
3647
.collect::<Result<Vec<_>, syn::Error>>()?;
3748

@@ -111,4 +122,52 @@ impl InMemoryGenerator {
111122
}
112123
})
113124
}
125+
126+
fn gen_range_index_fn(
127+
i: &Ident,
128+
idx: &Index,
129+
columns_map: &HashMap<Ident, TokenStream>,
130+
row_ident: Ident,
131+
column_range_type: &Ident,
132+
row_fields_ident: &Ident,
133+
) -> syn::Result<TokenStream> {
134+
let type_ = columns_map
135+
.get(i)
136+
.ok_or(syn::Error::new(i.span(), "Row not found"))?;
137+
let fn_name = Ident::new(format!("select_by_{i}_range").as_str(), Span::mixed_site());
138+
let field_ident = &idx.name;
139+
140+
let (range_bounds, range_arg) = if is_float(type_.to_string().as_str()) {
141+
(
142+
quote! { std::ops::RangeBounds<#type_> },
143+
quote! {
144+
(
145+
range.start_bound().map(|v| OrderedFloat(*v)),
146+
range.end_bound().map(|v| OrderedFloat(*v)),
147+
)
148+
},
149+
)
150+
} else {
151+
(
152+
quote! { std::ops::RangeBounds<#type_> },
153+
quote! { range },
154+
)
155+
};
156+
157+
Ok(quote! {
158+
pub fn #fn_name<R>(&self, range: R) -> SelectQueryBuilder<#row_ident,
159+
impl DoubleEndedIterator<Item = #row_ident> + '_,
160+
#column_range_type,
161+
#row_fields_ident>
162+
where
163+
R: #range_bounds
164+
{
165+
let rows = self.0.indexes.#field_ident
166+
.range(#range_arg)
167+
.filter_map(|(_, link)| self.0.data.select_non_ghosted(link.0).ok());
168+
169+
SelectQueryBuilder::new(rows)
170+
}
171+
})
172+
}
114173
}

codegen/src/generators/persist/table/impls.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ impl PersistGenerator {
1414
let name_fn = self.gen_table_name_fn();
1515
let version_fn = self.gen_table_version_fn();
1616
let select_fn = self.gen_table_select_fn();
17+
let select_range_fn = self.gen_table_select_range_fn();
1718
let insert_fn = self.gen_table_insert_fn();
1819
let reinsert_fn = self.gen_table_reinsert_fn();
1920
let upsert_fn = self.gen_table_upsert_fn();
@@ -30,6 +31,7 @@ impl PersistGenerator {
3031
#name_fn
3132
#version_fn
3233
#select_fn
34+
#select_range_fn
3335
#insert_fn
3436
#reinsert_fn
3537
#upsert_fn
@@ -158,6 +160,36 @@ impl PersistGenerator {
158160
}
159161
}
160162

163+
fn gen_table_select_range_fn(&self) -> TokenStream {
164+
let name_generator = WorktableNameGenerator::from_table_name(self.name.to_string());
165+
let row_type = name_generator.get_row_type_ident();
166+
let primary_key_type = name_generator.get_primary_key_type_ident();
167+
let column_range_type = name_generator.get_column_range_type_ident();
168+
let row_fields_ident = name_generator.get_row_fields_enum_ident();
169+
170+
quote! {
171+
pub fn select_by_pk_range<R, Pk>(&self, range: R) -> SelectQueryBuilder<#row_type,
172+
impl DoubleEndedIterator<Item = #row_type> + '_,
173+
#column_range_type,
174+
#row_fields_ident>
175+
where
176+
#primary_key_type: From<Pk>,
177+
R: std::ops::RangeBounds<Pk>,
178+
Pk: Clone,
179+
{
180+
let converted_range = (
181+
range.start_bound().map(|v| #primary_key_type::from(v.clone())),
182+
range.end_bound().map(|v| #primary_key_type::from(v.clone())),
183+
);
184+
let rows = self.0.primary_index.pk_map
185+
.range(converted_range)
186+
.filter_map(|(_, link)| self.0.data.select_non_ghosted(link.0).ok());
187+
188+
SelectQueryBuilder::new(rows)
189+
}
190+
}
191+
}
192+
161193
fn gen_table_insert_fn(&self) -> TokenStream {
162194
let name_generator = WorktableNameGenerator::from_table_name(self.name.to_string());
163195
let row_type = name_generator.get_row_type_ident();

codegen/src/generators/persist/table/index_fns.rs

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ impl PersistGenerator {
2020
.indexes
2121
.iter()
2222
.map(|(i, idx)| {
23-
if idx.is_unique {
24-
Self::gen_unique_index_fn(i, idx, &self.columns.columns_map, row_ident.clone())
23+
let point_fn = if idx.is_unique {
24+
Self::gen_unique_index_fn(i, idx, &self.columns.columns_map, row_ident.clone())?
2525
} else {
2626
Self::gen_non_unique_index_fn(
2727
i,
@@ -30,8 +30,19 @@ impl PersistGenerator {
3030
row_ident.clone(),
3131
&column_range_type,
3232
&row_fields_ident,
33-
)
34-
}
33+
)?
34+
};
35+
36+
let range_fn = Self::gen_range_index_fn(
37+
i,
38+
idx,
39+
&self.columns.columns_map,
40+
row_ident.clone(),
41+
&column_range_type,
42+
&row_fields_ident,
43+
)?;
44+
45+
Ok(quote! { #point_fn #range_fn })
3546
})
3647
.collect::<Result<Vec<_>, syn::Error>>()?;
3748

@@ -111,4 +122,52 @@ impl PersistGenerator {
111122
}
112123
})
113124
}
125+
126+
fn gen_range_index_fn(
127+
i: &Ident,
128+
idx: &Index,
129+
columns_map: &HashMap<Ident, TokenStream>,
130+
row_ident: Ident,
131+
column_range_type: &Ident,
132+
row_fields_ident: &Ident,
133+
) -> syn::Result<TokenStream> {
134+
let type_ = columns_map
135+
.get(i)
136+
.ok_or(syn::Error::new(i.span(), "Row not found"))?;
137+
let fn_name = Ident::new(format!("select_by_{i}_range").as_str(), Span::mixed_site());
138+
let field_ident = &idx.name;
139+
140+
let (range_bounds, range_arg) = if is_float(type_.to_string().as_str()) {
141+
(
142+
quote! { std::ops::RangeBounds<#type_> },
143+
quote! {
144+
(
145+
range.start_bound().map(|v| OrderedFloat(*v)),
146+
range.end_bound().map(|v| OrderedFloat(*v)),
147+
)
148+
},
149+
)
150+
} else {
151+
(
152+
quote! { std::ops::RangeBounds<#type_> },
153+
quote! { range },
154+
)
155+
};
156+
157+
Ok(quote! {
158+
pub fn #fn_name<R>(&self, range: R) -> SelectQueryBuilder<#row_ident,
159+
impl DoubleEndedIterator<Item = #row_ident> + '_,
160+
#column_range_type,
161+
#row_fields_ident>
162+
where
163+
R: #range_bounds
164+
{
165+
let rows = self.0.indexes.#field_ident
166+
.range(#range_arg)
167+
.filter_map(|(_, link)| self.0.data.select_non_ghosted(link.0).ok());
168+
169+
SelectQueryBuilder::new(rows)
170+
}
171+
})
172+
}
114173
}

codegen/src/generators/read_only/table/impls.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ impl ReadOnlyGenerator {
1313
let name_fn = self.gen_table_name_fn();
1414
let version_fn = self.gen_table_version_fn();
1515
let select_fn = self.gen_table_select_fn();
16+
let select_range_fn = self.gen_table_select_range_fn();
1617
let insert_fn = self.gen_table_insert_fn();
1718
let reinsert_fn = self.gen_table_reinsert_fn();
1819
let upsert_fn = self.gen_table_upsert_fn();
@@ -29,6 +30,7 @@ impl ReadOnlyGenerator {
2930
#name_fn
3031
#version_fn
3132
#select_fn
33+
#select_range_fn
3234
#insert_fn
3335
#reinsert_fn
3436
#upsert_fn
@@ -154,6 +156,36 @@ impl ReadOnlyGenerator {
154156
}
155157
}
156158

159+
fn gen_table_select_range_fn(&self) -> TokenStream {
160+
let name_generator = WorktableNameGenerator::from_table_name(self.name.to_string());
161+
let row_type = name_generator.get_row_type_ident();
162+
let primary_key_type = name_generator.get_primary_key_type_ident();
163+
let column_range_type = name_generator.get_column_range_type_ident();
164+
let row_fields_ident = name_generator.get_row_fields_enum_ident();
165+
166+
quote! {
167+
pub fn select_by_pk_range<R, Pk>(&self, range: R) -> SelectQueryBuilder<#row_type,
168+
impl DoubleEndedIterator<Item = #row_type> + '_,
169+
#column_range_type,
170+
#row_fields_ident>
171+
where
172+
#primary_key_type: From<Pk>,
173+
R: std::ops::RangeBounds<Pk>,
174+
Pk: Clone,
175+
{
176+
let converted_range = (
177+
range.start_bound().map(|v| #primary_key_type::from(v.clone())),
178+
range.end_bound().map(|v| #primary_key_type::from(v.clone())),
179+
);
180+
let rows = self.0.primary_index.pk_map
181+
.range(converted_range)
182+
.filter_map(|(_, link)| self.0.data.select_non_ghosted(link.0).ok());
183+
184+
SelectQueryBuilder::new(rows)
185+
}
186+
}
187+
}
188+
157189
fn gen_table_insert_fn(&self) -> TokenStream {
158190
quote! {}
159191
}

0 commit comments

Comments
 (0)