Skip to content

Commit

Permalink
all tests working
Browse files Browse the repository at this point in the history
  • Loading branch information
kurtbuilds committed Dec 28, 2023
1 parent 4ea0ccf commit abddb9c
Show file tree
Hide file tree
Showing 10 changed files with 223 additions and 189 deletions.
60 changes: 8 additions & 52 deletions macro/src/codegen/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,22 +74,24 @@ fn recursive_primitive_types<'a>(table: &'a ModelMetadata, cache: &'a MetadataCa
.collect()
}

fn table_primitive_types<'a>(attr: &'a TableMetadata, cache: &'a MetadataCache) -> Vec<Cow<'a, InnerType>> {
pub(crate) fn table_primitive_types<'a>(attr: &'a TableMetadata, cache: &'a MetadataCache) -> Vec<Cow<'a, InnerType>> {
attr.columns.iter()
.filter(|c| !c.skip)
.filter(|c| !c.experimental_encode_as_json)
.map(|c| recursive_primitive_types_ty(&c.column_type, cache))
.flatten()
.unique()
.collect()
}

pub fn from_row_bounds<'a>(attr: &'a TableMetadata, cache: &'a MetadataCache) -> impl Iterator<Item=proc_macro2::TokenStream> + 'a {
pub fn from_row_bounds<'a>(db: &dyn OrmliteCodegen, attr: &'a TableMetadata, cache: &'a MetadataCache) -> impl Iterator<Item=proc_macro2::TokenStream> + 'a {
let database = db.database_ts();
table_primitive_types(attr, cache)
.into_iter()
.map(|ty| {
.map(move |ty| {
quote! {
#ty: ::ormlite::decode::Decode<'a, R::Database>,
#ty: ::ormlite::types::Type<R::Database>,
#ty: ::ormlite::decode::Decode<'a, #database>,
#ty: ::ormlite::types::Type<#database>,
}
})
}
Expand Down Expand Up @@ -124,52 +126,6 @@ pub trait OrmliteCodegen {
// A placeholder that works at the phase when its invoked (e.g. during comp time, it can be used.
// Compare to placeholder_ts, which is just the tokens of a placeholder, and therefore can't be "used" until runtime.
fn placeholder(&self) -> Placeholder;
fn row(&self) -> TokenStream;

}

#[cfg(test)]
mod test {
use super::*;
use ormlite_attr::*;

#[test]
fn test_all_bounds() {
let mut cache = MetadataCache::new();
let table = ModelMetadata::new("user", vec![
ColumnMetadata::new("id", "u32"),
ColumnMetadata::new("name", "String"),
ColumnMetadata::new("organization_id", "u32"),
ColumnMetadata::new_join("organization", "Organization"),
]);
cache.insert("User".to_string(), table.clone());
let table = ModelMetadata::new("organization", vec![
ColumnMetadata::new("id", "u32"),
ColumnMetadata::new("name", "String"),
ColumnMetadata::new("is_active", "bool"),
]);
cache.insert("Organization".to_string(), table.clone());

let types_for_bound = table_primitive_types(&table.inner, &cache);
let types_for_bound = types_for_bound.into_iter().map(|c| c.into_owned()).collect::<Vec<_>>();
assert_eq!(types_for_bound, vec![
InnerType::new("u32"),
InnerType::new("String"),
InnerType::new("bool"),
]);
let bounds = from_row_bounds(&table.inner, &cache);
let bounds = quote! {
#(#bounds)*
};
assert_eq!(
bounds.to_string(),
"u32 : :: ormlite :: decode :: Decode < 'a , R :: Database > , ".to_owned() +
"u32 : :: ormlite :: types :: Type < R :: Database > , " +

"String : :: ormlite :: decode :: Decode < 'a , R :: Database > , " +
"String : :: ormlite :: types :: Type < R :: Database > , " +

"bool : :: ormlite :: decode :: Decode < 'a , R :: Database > , " +
"bool : :: ormlite :: types :: Type < R :: Database > ,"
);
}
}
33 changes: 20 additions & 13 deletions macro/src/codegen/from_row.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use proc_macro2::TokenStream;
use quote::quote;
use ormlite_attr::{ColumnMetadata, Ident, TableMetadata};
use crate::codegen::common::from_row_bounds;
use crate::codegen::common::{from_row_bounds, OrmliteCodegen};
use crate::MetadataCache;

pub fn impl_FromRow(attr: &TableMetadata, cache: &MetadataCache) -> TokenStream {
let bounds = from_row_bounds(attr, cache);
pub fn impl_FromRow(db: &dyn OrmliteCodegen, attr: &TableMetadata, cache: &MetadataCache) -> TokenStream {
let bounds = from_row_bounds(db, attr, cache);
let row = db.row();

let prefix_branches = attr.columns.iter().filter(|c| c.is_join()).map(|c| {
let name = &c.identifier.to_string();
Expand Down Expand Up @@ -39,7 +40,7 @@ pub fn impl_FromRow(attr: &TableMetadata, cache: &MetadataCache) -> TokenStream

let map_join = if attr.columns.iter().any(|c| c.is_join()) {
quote! {
let mut prefixes = row.columns().iter().filter_map(|c| {
let mut prefixes = ::ormlite::Row::columns(row).iter().filter_map(|c| {
let name = ::ormlite::Column::name(c);
if name.starts_with("__") {
name.rsplitn(2, "__").last().map(|s| &s[2..])
Expand Down Expand Up @@ -68,14 +69,14 @@ pub fn impl_FromRow(attr: &TableMetadata, cache: &MetadataCache) -> TokenStream
};
let model = &attr.struct_name;
quote! {
impl<'a, R: ::ormlite::Row> ::ormlite::model::FromRow<'a, R> for #model
impl<'a> ::ormlite::model::FromRow<'a, #row> for #model
where
&'a str: ::ormlite::ColumnIndex<R>,
// &'a str: ::ormlite::ColumnIndex<#row>,
#(
#bounds
)*
{
fn from_row(row: &'a R) -> ::std::result::Result<Self, ::ormlite::SqlxError> {
fn from_row(row: &'a #row) -> ::std::result::Result<Self, ::ormlite::SqlxError> {
let mut model = Self::from_row_using_aliases(row, &[
#(
#field_names,
Expand All @@ -89,9 +90,10 @@ pub fn impl_FromRow(attr: &TableMetadata, cache: &MetadataCache) -> TokenStream
}


pub fn impl_from_row_using_aliases(attr: &TableMetadata, metadata_cache: &MetadataCache) -> TokenStream {
pub fn impl_from_row_using_aliases(db: &dyn OrmliteCodegen, attr: &TableMetadata, metadata_cache: &MetadataCache) -> TokenStream {
let row = db.row();
let fields = attr.all_fields();
let bounds = from_row_bounds(attr, &metadata_cache);
let bounds = from_row_bounds(db, attr, &metadata_cache);
let mut incrementer = 0usize..;
let columns = attr.columns.iter()
.map(|c| {
Expand All @@ -104,9 +106,9 @@ pub fn impl_from_row_using_aliases(attr: &TableMetadata, metadata_cache: &Metada
let model = &attr.struct_name;
quote! {
impl #model {
pub fn from_row_using_aliases<'a, R: ::ormlite::Row>(row: &'a R, aliases: &'a [&str]) -> ::std::result::Result<Self, ::ormlite::SqlxError>
pub fn from_row_using_aliases<'a>(row: &'a #row, aliases: &'a [&str]) -> ::std::result::Result<Self, ::ormlite::SqlxError>
where
&'a str: ::ormlite::ColumnIndex<R>,
// &'a str: ::ormlite::ColumnIndex<#row>,
#(
#bounds
)*
Expand All @@ -132,12 +134,17 @@ pub fn from_row_for_column(get_value: TokenStream, col: &ColumnMetadata) -> Toke
} else if col.is_join() {
let id_id = Ident::new(&format!("{}_id", id));
quote! {
let #id_id: <#ty as ::ormlite::model::JoinMeta>::IdType = row.try_get(#get_value)?;
let #id_id: <#ty as ::ormlite::model::JoinMeta>::IdType = ::ormlite::Row::try_get(row, #get_value)?;
let #id = ::ormlite::model::Join::new_with_id(#id_id);
}
} else if col.experimental_encode_as_json {
quote! {
let #id: ::ormlite::types::Json<#ty> = ::ormlite::Row::try_get(row, #get_value)?;
let #id = #id.0;
}
} else {
quote! {
let #id: #ty = row.try_get(#get_value)?;
let #id: #ty = ::ormlite::Row::try_get(row, #get_value)?;
}
}
}
59 changes: 57 additions & 2 deletions macro/src/codegen/postgres.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use crate::codegen::common::OrmliteCodegen;
use crate::codegen::common::{from_row_bounds, OrmliteCodegen};
use ormlite_attr::TableMetadata;
use ormlite_core::query_builder::Placeholder;
use proc_macro2::TokenStream;
use quote::quote;
use syn::DeriveInput;
use crate::MetadataCache;

pub struct PostgresBackend {}
pub struct PostgresBackend;

impl OrmliteCodegen for PostgresBackend {
fn database_ts(&self) -> TokenStream {
Expand All @@ -22,4 +23,58 @@ impl OrmliteCodegen for PostgresBackend {
Placeholder::dollar_sign()
}

fn row(&self) -> TokenStream {
quote! {
::ormlite::postgres::PgRow
}
}
}


#[cfg(test)]
mod test {
use super::*;
use ormlite_attr::*;

#[test]
fn test_all_bounds() {
let db = PostgresBackend;
let mut cache = MetadataCache::new();
let table = ModelMetadata::new("user", vec![
ColumnMetadata::new("id", "u32"),
ColumnMetadata::new("name", "String"),
ColumnMetadata::new("organization_id", "u32"),
ColumnMetadata::new_join("organization", "Organization"),
]);
cache.insert("User".to_string(), table.clone());
let table = ModelMetadata::new("organization", vec![
ColumnMetadata::new("id", "u32"),
ColumnMetadata::new("name", "String"),
ColumnMetadata::new("is_active", "bool"),
]);
cache.insert("Organization".to_string(), table.clone());

let types_for_bound = crate::codegen::common::table_primitive_types(&table.inner, &cache);
let types_for_bound = types_for_bound.into_iter().map(|c| c.into_owned()).collect::<Vec<_>>();
assert_eq!(types_for_bound, vec![
InnerType::new("u32"),
InnerType::new("String"),
InnerType::new("bool"),
]);
let bounds = from_row_bounds(&db, &table.inner, &cache);
let bounds = quote! {
#(#bounds)*
};
assert_eq!(
bounds.to_string(),
"u32 : :: ormlite :: decode :: Decode < 'a , R :: Database > , ".to_owned() +
"u32 : :: ormlite :: types :: Type < R :: Database > , " +

"String : :: ormlite :: decode :: Decode < 'a , R :: Database > , " +
"String : :: ormlite :: types :: Type < R :: Database > , " +

"bool : :: ormlite :: decode :: Decode < 'a , R :: Database > , " +
"bool : :: ormlite :: types :: Type < R :: Database > ,"
);
}
}
6 changes: 6 additions & 0 deletions macro/src/codegen/sqlite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,10 @@ impl OrmliteCodegen for SqliteBackend {
fn placeholder(&self) -> Placeholder {
Placeholder::question_mark()
}

fn row(&self) -> TokenStream {
quote! {
::ormlite::sqlite::SqliteRow
}
}
}
15 changes: 8 additions & 7 deletions macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ fn get_databases(table_meta: &TableMetadata) -> Vec<Box<dyn OrmliteCodegen>> {
#[cfg(feature = "default-sqlite")]
databases.push(Box::new(codegen::sqlite::SqliteBackend {}));
#[cfg(feature = "default-postgres")]
databases.push(Box::new(codegen::postgres::PostgresBackend {}));
databases.push(Box::new(codegen::postgres::PostgresBackend));
#[cfg(feature = "default-mysql")]
databases.push(Box::new(codegen::mysql::MysqlBackend {}));
} else {
Expand All @@ -64,7 +64,7 @@ fn get_databases(table_meta: &TableMetadata) -> Vec<Box<dyn OrmliteCodegen>> {
#[cfg(feature = "sqlite")]
"sqlite" => databases.push(Box::new(codegen::sqlite::SqliteBackend {})),
#[cfg(feature = "postgres")]
"postgres" => databases.push(Box::new(codegen::postgres::PostgresBackend {})),
"postgres" => databases.push(Box::new(codegen::postgres::PostgresBackend)),
#[cfg(feature = "mysql")]
"mysql" => databases.push(Box::new(codegen::mysql::MysqlBackend {})),
"sqlite" | "postgres" | "mysql" => panic!("Database {} is not enabled. Enable it with features = [\"{}\"]", db, db),
Expand Down Expand Up @@ -96,7 +96,7 @@ fn get_databases(table_meta: &TableMetadata) -> Vec<Box<dyn OrmliteCodegen>> {
#[cfg(feature = "sqlite")]
databases.push(Box::new(codegen::sqlite::SqliteBackend {}));
#[cfg(feature = "postgres")]
databases.push(Box::new(codegen::postgres::PostgresBackend {}));
databases.push(Box::new(codegen::postgres::PostgresBackend));
#[cfg(feature = "mysql")]
databases.push(Box::new(codegen::mysql::MysqlBackend {}));
}
Expand Down Expand Up @@ -124,8 +124,8 @@ pub fn expand_ormlite_model(input: TokenStream) -> TokenStream {
let static_join_descriptions = static_join_descriptions(&meta.inner, &tables);
let impl_Model = impl_Model(db, &meta, tables);
let impl_HasModelBuilder = impl_HasModelBuilder(db, &meta);
let impl_FromRow = impl_FromRow(&meta.inner, &tables);
let impl_from_row_using_aliases = impl_from_row_using_aliases(&meta.inner, &tables);
let impl_FromRow = impl_FromRow(db, &meta.inner, &tables);
let impl_from_row_using_aliases = impl_from_row_using_aliases(db, &meta.inner, &tables);

let struct_ModelBuilder = struct_ModelBuilder(&ast, &meta);
let impl_ModelBuilder = impl_ModelBuilder(db, &meta);
Expand Down Expand Up @@ -175,8 +175,9 @@ pub fn expand_derive_fromrow(input: TokenStream) -> TokenStream {
let tables = get_tables();

let expanded = databases.iter().map(|db| {
let impl_FromRow = impl_FromRow(&meta, &tables);
let impl_from_row_using_aliases = impl_from_row_using_aliases(&meta, &tables);
let db = db.as_ref();
let impl_FromRow = impl_FromRow(db, &meta, &tables);
let impl_from_row_using_aliases = impl_from_row_using_aliases(db, &meta, &tables);
quote! {
#impl_FromRow
#impl_from_row_using_aliases
Expand Down
7 changes: 6 additions & 1 deletion ormlite/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ homepage = "https://github.com/kurtbuilds/ormlite"
documentation = "https://docs.rs/ormlite"
autotests = false
readme = "../README.md"
autoexamples = false
# autoexamples = false

[package.metadata.docs.rs]
rustdoc-args = ["--cfg", "docsrs"]
Expand All @@ -21,6 +21,11 @@ name = "sqlite"
path = "tests/sqlite.rs"
required-features = ["sqlite"]

[[test]]
name = "simple"
path = "tests/simple.rs"
required-features = ["sqlite"]

[[test]]
name = "postgres"
path = "tests/postgres.rs"
Expand Down
2 changes: 1 addition & 1 deletion ormlite/Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ expand-run:
printf '#![feature(fmt_helpers_for_derive)]\n' >> examples/expand.rs
printf '#![feature(print_internals)]\n' >> examples/expand.rs
printf '#![feature(core_panic)]\n' >> examples/expand.rs
cargo expand --example many-to-one --features sqlite,uuid >> examples/expand.rs
cargo expand --example simple --features sqlite,uuid >> examples/expand.rs
sd '::alloc::' '::std::' examples/expand.rs -f
sd '# ?\[ormlite.*' '' examples/expand.rs -f
sd -s '#[rustc_box]' '' examples/expand.rs -f
Expand Down
Loading

0 comments on commit abddb9c

Please sign in to comment.