Skip to content

Commit fb18363

Browse files
committed
get any getter for postgres backend
1 parent b8cde44 commit fb18363

File tree

5 files changed

+77
-6
lines changed

5 files changed

+77
-6
lines changed

ormx-macros/src/attrs.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ pub enum TableFieldAttr {
2929
GetOptional(Getter),
3030
// get_many [= <ident>]? [(<type>)]?
3131
GetMany(Getter),
32+
// get_many [= <ident>]? [(<type>)]?
33+
#[cfg(feature = "postgres")]
34+
GetAny(Getter),
3235
// set [= <ident>]?
3336
Set(Option<Ident>),
3437
}
@@ -95,14 +98,16 @@ pub fn parse_attrs<A: Parse>(attrs: &[Attribute]) -> Result<Vec<A>> {
9598
macro_rules! impl_parse {
9699
// entry point
97100
($i:ident {
98-
$( $s:literal => $v:ident( $($t:tt)* ) ),*
101+
$( $(#[cfg($cfg_attr: meta)])? $s:literal => $v:ident( $($t:tt)* ) ),*
99102
}) => {
100103
impl syn::parse::Parse for $i {
101104
#[allow(clippy::redundant_closure_call)]
102105
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
103106
let ident = input.parse::<syn::Ident>()?;
104107
match &*ident.to_string() {
105-
$( $s => (impl_parse!($($t)*))(input).map(Self::$v), )*
108+
$(
109+
$(#[cfg($cfg_attr)])?
110+
$s => (impl_parse!($($t)*))(input).map(Self::$v), )*
106111
_ => Err(input.error("unknown attribute"))
107112
}
108113
}
@@ -141,6 +146,8 @@ impl_parse!(TableFieldAttr {
141146
"get_one" => GetOne(Getter),
142147
"get_optional" => GetOptional(Getter),
143148
"get_many" => GetMany(Getter),
149+
#[cfg(feature = "postgres")]
150+
"get_any" => GetAny(Getter),
144151
"set" => Set((= Ident)?),
145152
"custom_type" => CustomType(),
146153
"default" => Default()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
use crate::{
2+
backend::{common, postgres::PgBindings},
3+
table::Table,
4+
};
5+
6+
use super::PgBackend;
7+
use proc_macro2::TokenStream;
8+
use quote::quote;
9+
10+
pub(crate) fn impl_get_any_getter(table: &Table<PgBackend>) -> TokenStream {
11+
let column_list = table.select_column_list();
12+
let vis = &table.vis;
13+
let mut getters = TokenStream::new();
14+
15+
for field in table.fields.iter() {
16+
if let Some(getter) = &field.get_any {
17+
let sql = format!(
18+
"SELECT {} FROM {} WHERE {} = ANY({})",
19+
column_list,
20+
table.table,
21+
field.column(),
22+
PgBindings::default().next().unwrap()
23+
);
24+
25+
let func = getter.ident_or_fallback(&field);
26+
let arg = getter.arg_ty.clone().unwrap_or_else(|| {
27+
let ty = &field.ty;
28+
syn::parse2(quote!(&[#ty])).unwrap()
29+
});
30+
31+
getters.extend(common::get_many(vis, &func, &arg, &sql));
32+
}
33+
}
34+
35+
let table_ident = &table.ident;
36+
quote! {
37+
impl #table_ident {
38+
#getters
39+
}
40+
}
41+
}

ormx-macros/src/backend/postgres/mod.rs

+11
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ use proc_macro2::TokenStream;
55
use crate::backend::Backend;
66
use crate::table::Table;
77

8+
use self::get_any::impl_get_any_getter;
9+
10+
use super::common;
11+
12+
mod get_any;
813
mod insert;
914

1015
#[derive(Clone)]
@@ -32,6 +37,12 @@ impl Backend for PgBackend {
3237
fn impl_insert(table: &Table<Self>) -> TokenStream {
3338
insert::impl_insert(table)
3439
}
40+
41+
fn impl_getters(table: &Table<Self>) -> TokenStream {
42+
let mut getters = common::getters::<Self>(table);
43+
getters.extend(impl_get_any_getter(table));
44+
getters
45+
}
3546
}
3647

3748
#[derive(Default)]

ormx-macros/src/table/mod.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ pub struct TableField<B: Backend> {
3232
pub get_one: Option<Getter>,
3333
pub get_optional: Option<Getter>,
3434
pub get_many: Option<Getter>,
35+
#[cfg(feature = "postgres")]
36+
pub get_any: Option<Getter>,
3537
pub set: Option<Ident>,
3638
pub _phantom: PhantomData<*const B>,
3739
}
@@ -86,16 +88,19 @@ impl<B: Backend> TableField<B> {
8688

8789
impl Getter {
8890
pub fn or_fallback<B: Backend>(&self, field: &TableField<B>) -> (Ident, Type) {
89-
let ident = self
90-
.func
91-
.clone()
92-
.unwrap_or_else(|| Ident::new(&format!("by_{}", field.field), Span::call_site()));
91+
let ident = self.ident_or_fallback(field);
9392
let arg = self.arg_ty.clone().unwrap_or_else(|| {
9493
let ty = &field.ty;
9594
syn::parse2(quote!(&#ty)).unwrap()
9695
});
9796
(ident, arg)
9897
}
98+
99+
pub fn ident_or_fallback<B: Backend>(&self, field: &TableField<B>) -> Ident {
100+
self.func
101+
.clone()
102+
.unwrap_or_else(|| Ident::new(&format!("by_{}", field.field), Span::call_site()))
103+
}
99104
}
100105

101106
pub fn derive(input: DeriveInput) -> Result<TokenStream> {

ormx-macros/src/table/parse.rs

+7
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,18 @@ impl<B: Backend> TryFrom<&syn::Field> for TableField<B> {
3838
default
3939
);
4040

41+
#[cfg(feature = "postgres")]
42+
none!(get_any);
43+
4144
for attr in parse_attrs::<TableFieldAttr>(&value.attrs)? {
4245
match attr {
4346
TableFieldAttr::Column(c) => set_once(&mut column, c)?,
4447
TableFieldAttr::CustomType(..) => set_once(&mut custom_type, true)?,
4548
TableFieldAttr::GetOne(g) => set_once(&mut get_one, g)?,
4649
TableFieldAttr::GetOptional(g) => set_once(&mut get_optional, g)?,
4750
TableFieldAttr::GetMany(g) => set_once(&mut get_many, g)?,
51+
#[cfg(feature = "postgres")]
52+
TableFieldAttr::GetAny(g) => set_once(&mut get_any, g)?,
4853
TableFieldAttr::Set(s) => {
4954
let default = || Ident::new(&format!("set_{}", ident), Span::call_site());
5055
set_once(&mut set, s.unwrap_or_else(default))?
@@ -62,6 +67,8 @@ impl<B: Backend> TryFrom<&syn::Field> for TableField<B> {
6267
get_one,
6368
get_optional,
6469
get_many,
70+
#[cfg(feature = "postgres")]
71+
get_any,
6572
set,
6673
_phantom: PhantomData,
6774
})

0 commit comments

Comments
 (0)