From de929feb499550d7c6eb9dc3d8780d150c8405d7 Mon Sep 17 00:00:00 2001 From: Kurt Wolf Date: Sat, 31 Aug 2024 12:04:04 -0700 Subject: [PATCH] rustfmt --- .rustfmt.toml | 1 + attr/src/attr.rs | 4 +- attr/src/derive.rs | 24 +++++-- attr/src/ext.rs | 2 +- attr/src/lib.rs | 46 ++++-------- attr/src/metadata/column.rs | 23 +++--- attr/src/metadata/model.rs | 41 ++++++----- attr/src/metadata/table.rs | 34 +++++---- attr/src/repr.rs | 11 ++- attr/src/ttype.rs | 9 +-- cli/src/command.rs | 8 +-- cli/src/command/down.rs | 57 +++++++++------ cli/src/command/init.rs | 15 ++-- cli/src/command/migrate.rs | 100 ++++++++++++++++---------- cli/src/command/up.rs | 28 +++++--- cli/src/main.rs | 18 +++-- cli/src/util.rs | 2 +- core/src/config.rs | 3 +- core/src/error.rs | 2 +- core/src/insert.rs | 11 +-- core/src/join.rs | 69 +++++++++--------- core/src/lib.rs | 7 +- core/src/model.rs | 62 ++++++++-------- core/src/query_builder/args.rs | 5 +- core/src/query_builder/mod.rs | 2 +- core/src/query_builder/select.rs | 16 ++--- core/src/query_builder/util.rs | 52 +++++++------- core/src/schema.rs | 65 +++++++++-------- macro/src/codegen.rs | 18 ++--- macro/src/codegen/common.rs | 51 +++++++------ macro/src/codegen/from_row.rs | 32 +++++---- macro/src/codegen/insert.rs | 54 +++++++------- macro/src/codegen/insert_model.rs | 22 +++--- macro/src/codegen/into_arguments.rs | 33 +++++---- macro/src/codegen/join_description.rs | 20 +++--- macro/src/codegen/meta.rs | 7 +- macro/src/codegen/model.rs | 9 +-- macro/src/codegen/model_builder.rs | 70 +++++++++--------- macro/src/codegen/mysql.rs | 2 +- macro/src/codegen/postgres.rs | 56 ++++++++------- macro/src/codegen/select.rs | 6 +- macro/src/codegen/update.rs | 67 +++++++++-------- macro/src/lib.rs | 34 ++++++--- macro/src/util.rs | 2 - ormlite/src/lib.rs | 18 ++--- ormlite/src/model.rs | 6 +- ormlite/tests/postgres.rs | 2 +- ormlite/tests/run.rs | 3 +- ormlite/tests/simple.rs | 23 ++---- 49 files changed, 638 insertions(+), 614 deletions(-) create mode 100644 .rustfmt.toml diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 00000000..75306517 --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1 @@ +max_width = 120 diff --git a/attr/src/attr.rs b/attr/src/attr.rs index 594b7954..be4c0047 100644 --- a/attr/src/attr.rs +++ b/attr/src/attr.rs @@ -90,7 +90,7 @@ pub struct ColumnAttributes { #[cfg(test)] mod test { - use syn::{Attribute, parse_quote}; + use syn::{parse_quote, Attribute}; use super::*; @@ -111,4 +111,4 @@ mod test { let args: ColumnAttributes = attr.parse_args().unwrap(); assert!(args.join_column.is_some()); } -} \ No newline at end of file +} diff --git a/attr/src/derive.rs b/attr/src/derive.rs index aec8c64e..a1a1f194 100644 --- a/attr/src/derive.rs +++ b/attr/src/derive.rs @@ -1,6 +1,6 @@ -use syn::{Meta, Path, Token}; use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; +use syn::{Meta, Path, Token}; use crate::cfg_attr::CfgAttr; @@ -75,15 +75,21 @@ impl DeriveParser { pub fn from_attributes(attrs: &[syn::Attribute]) -> Self { let mut result = Self::default(); for attr in attrs { - let Some(ident) = attr.path().get_ident() else { continue; }; + let Some(ident) = attr.path().get_ident() else { + continue; + }; if ident == Self::ATTRIBUTE { result.merge(attr.parse_args().unwrap()); } else if ident == "cfg_attr" { let cfg: CfgAttr = attr.parse_args().unwrap(); for attr in cfg.attrs { - let Some(ident) = attr.path().get_ident() else { continue; }; + let Some(ident) = attr.path().get_ident() else { + continue; + }; if ident == Self::ATTRIBUTE { - let Meta::List(attrs) = attr else { panic!("Expected a list of attributes") }; + let Meta::List(attrs) = attr else { + panic!("Expected a list of attributes") + }; result.merge(attrs.parse_args().unwrap()); } } @@ -108,8 +114,8 @@ impl Parse for Derive { #[cfg(test)] mod tests { - use crate::repr::Repr; use super::*; + use crate::repr::Repr; #[test] fn test_repr() { @@ -182,7 +188,9 @@ pub enum Privacy { } "#; let file: syn::File = syn::parse_str(code).unwrap(); - let syn::Item::Enum(item) = file.items.first().unwrap() else { panic!() }; + let syn::Item::Enum(item) = file.items.first().unwrap() else { + panic!() + }; let attr = DeriveParser::from_attributes(&item.attrs); assert!(attr.has_derive2(&["ormlite", "sqlx"], "Type")); } @@ -209,7 +217,9 @@ pub enum Privacy { } "#; let file: syn::File = syn::parse_str(code).unwrap(); - let syn::Item::Enum(item) = file.items.first().unwrap() else { panic!() }; + let syn::Item::Enum(item) = file.items.first().unwrap() else { + panic!() + }; let attr = DeriveParser::from_attributes(&item.attrs); assert_eq!(attr.has_derive("ormlite", "ManualType"), true); } diff --git a/attr/src/ext.rs b/attr/src/ext.rs index 710d726d..c479820c 100644 --- a/attr/src/ext.rs +++ b/attr/src/ext.rs @@ -16,4 +16,4 @@ impl DeriveInputExt for DeriveInput { }; fields.iter() } -} \ No newline at end of file +} diff --git a/attr/src/lib.rs b/attr/src/lib.rs index 7e686af9..c0913e05 100644 --- a/attr/src/lib.rs +++ b/attr/src/lib.rs @@ -59,11 +59,7 @@ impl Intermediate { .type_structs .into_iter() .map(|(s, a)| (s.ident.to_string(), a)) - .chain( - self.type_enums - .into_iter() - .map(|(e, a)| (e.ident.to_string(), a)), - ); + .chain(self.type_enums.into_iter().map(|(e, a)| (e.ident.to_string(), a))); (models, types) } @@ -90,9 +86,7 @@ impl Intermediate { } Item::Enum(e) => { let attrs = DeriveParser::from_attributes(&e.attrs); - if attrs.has_derive("ormlite", "Type") - || attrs.has_derive("ormlite", "ManualType") - { + if attrs.has_derive("ormlite", "Type") || attrs.has_derive("ormlite", "ManualType") { tracing::debug!(r#type=%e.ident.to_string(), "Found"); let repr = Repr::from_attributes(&e.attrs); type_enums.push((e, repr)); @@ -110,14 +104,12 @@ impl Intermediate { } pub fn schema_from_filepaths(paths: &[&Path]) -> anyhow::Result { - let cwd = env::var("CARGO_MANIFEST_DIR").map(PathBuf::from) + let cwd = env::var("CARGO_MANIFEST_DIR") + .map(PathBuf::from) .or_else(|_| env::current_dir()) .expect("Failed to get current directory for schema"); let paths = paths.iter().map(|p| cwd.join(p)).collect::>(); - let invalid_paths = paths - .iter() - .filter(|p| fs::metadata(p).is_err()) - .collect::>(); + let invalid_paths = paths.iter().filter(|p| fs::metadata(p).is_err()).collect::>(); if !invalid_paths.is_empty() { for path in &invalid_paths { tracing::error!(path = path.display().to_string(), "Does not exist"); @@ -136,46 +128,32 @@ pub fn schema_from_filepaths(paths: &[&Path]) -> anyhow::Result { .map(|e| e.unwrap()) .filter(|e| e.path().extension().map(|e| e == "rs").unwrap_or(false)) .map(|e| e.into_path()) - .chain( - paths - .iter() - .filter(|p| p.ends_with(".rs")) - .map(|p| p.to_path_buf()), - ); + .chain(paths.iter().filter(|p| p.ends_with(".rs")).map(|p| p.to_path_buf())); let mut tables = vec![]; let mut type_aliases = HashMap::new(); for entry in walk { - let contents = fs::read_to_string(&entry) - .context(format!("failed to read file: {}", entry.display()))?; + let contents = fs::read_to_string(&entry).context(format!("failed to read file: {}", entry.display()))?; tracing::debug!( file = entry.display().to_string(), "Checking for Model, Type, ManualType derive attrs" ); - if !(contents.contains("Model") - || contents.contains("Type") - || contents.contains("ManualType")) - { + if !(contents.contains("Model") || contents.contains("Type") || contents.contains("ManualType")) { continue; } - let ast = syn::parse_file(&contents) - .context(format!("Failed to parse file: {}", entry.display()))?; + let ast = syn::parse_file(&contents).context(format!("Failed to parse file: {}", entry.display()))?; let intermediate = Intermediate::from_file(ast); let (models, types) = intermediate.into_models_and_types(); for item in models { let derive: DeriveInput = item.into(); - let table = ModelMetadata::from_derive(&derive).context(format!( - "Failed to parse model: {}", - derive.ident.to_string() - ))?; + let table = ModelMetadata::from_derive(&derive) + .context(format!("Failed to parse model: {}", derive.ident.to_string()))?; tables.push(table); } for (name, repr) in types { - let ty = repr - .map(|s| s.to_string()) - .unwrap_or_else(|| "String".to_string()); + let ty = repr.map(|s| s.to_string()).unwrap_or_else(|| "String".to_string()); type_aliases.insert(name, ty); } } diff --git a/attr/src/metadata/column.rs b/attr/src/metadata/column.rs index b43017ad..fdd41500 100644 --- a/attr/src/metadata/column.rs +++ b/attr/src/metadata/column.rs @@ -1,8 +1,8 @@ -use proc_macro2::TokenStream; -use syn::Field; -use crate::{ColumnAttributes, SyndecodeError}; use crate::ident::Ident; use crate::ttype::{InnerType, TType}; +use crate::{ColumnAttributes, SyndecodeError}; +use proc_macro2::TokenStream; +use syn::Field; #[derive(Debug, Clone)] pub enum Join { @@ -110,7 +110,6 @@ impl ColumnMetadata { } } - impl TryFrom<&Field> for ColumnMetadata { type Error = SyndecodeError; @@ -176,7 +175,6 @@ impl TryFrom<&Field> for ColumnMetadata { } } - #[derive(Clone, Debug)] pub struct ForeignKey { pub model: String, @@ -185,18 +183,23 @@ pub struct ForeignKey { #[cfg(test)] mod tests { - use syn::{Fields, ItemStruct}; use super::*; + use syn::{Fields, ItemStruct}; #[test] fn test_from_field() { - let item: ItemStruct = syn::parse_str(r#" + let item: ItemStruct = syn::parse_str( + r#" struct Foo { #[ormlite(default_value = "\"foo\".to_string()")] pub name: String } -"#).unwrap(); - let Fields::Named(fields) = item.fields else { panic!(); }; +"#, + ) + .unwrap(); + let Fields::Named(fields) = item.fields else { + panic!(); + }; let field = fields.named.first().unwrap(); let column = ColumnMetadata::try_from(field).unwrap(); assert_eq!(column.column_name, "name"); @@ -206,4 +209,4 @@ pub name: String assert_eq!(column.rust_default, Some("\"foo\".to_string()".to_string())); assert_eq!(column.identifier, Ident::new("name")); } -} \ No newline at end of file +} diff --git a/attr/src/metadata/model.rs b/attr/src/metadata/model.rs index 4423128a..142202e2 100644 --- a/attr/src/metadata/model.rs +++ b/attr/src/metadata/model.rs @@ -1,8 +1,8 @@ -use syn::DeriveInput; use crate::ident::Ident; use crate::metadata::column::ColumnMetadata; -use crate::{ModelAttributes, SyndecodeError}; use crate::metadata::table::TableMetadata; +use crate::{ModelAttributes, SyndecodeError}; +use syn::DeriveInput; /// Metadata used for IntoArguments, TableMeta, and (subset of) Model #[derive(Debug, Clone)] @@ -16,10 +16,7 @@ impl ModelMetadata { pub fn new(name: &str, columns: Vec) -> Self { let inner = TableMetadata::new(name, columns); Self { - pkey: inner.columns.iter() - .find(|c| c.column_name == "id") - .unwrap() - .clone(), + pkey: inner.columns.iter().find(|c| c.column_name == "id").unwrap().clone(), inner, insert_struct: None, } @@ -38,21 +35,23 @@ impl ModelMetadata { Ident(s) } - pub fn database_columns_except_pkey(&self) -> impl Iterator + '_ { - self.inner.columns.iter() + pub fn database_columns_except_pkey(&self) -> impl Iterator + '_ { + self.inner + .columns + .iter() .filter(|&c| !c.skip) .filter(|&c| self.pkey.column_name != c.column_name) } - pub fn database_columns(&self) -> impl Iterator + '_ { + pub fn database_columns(&self) -> impl Iterator + '_ { self.inner.database_columns() } - pub fn many_to_one_joins(&self) -> impl Iterator + '_ { + pub fn many_to_one_joins(&self) -> impl Iterator + '_ { self.inner.many_to_one_joins() } - pub fn columns(&self) -> impl Iterator + '_ { + pub fn columns(&self) -> impl Iterator + '_ { self.inner.columns.iter() } @@ -65,13 +64,16 @@ impl ModelMetadata { let pkey = inner.columns.iter().find(|&c| c.column_name == pkey).unwrap().clone(); let mut insert_struct = None; for attr in ast.attrs.iter().filter(|a| a.path().is_ident("ormlite")) { - let args: ModelAttributes = attr.parse_args() - .map_err(|e| SyndecodeError(e.to_string()))?; + let args: ModelAttributes = attr.parse_args().map_err(|e| SyndecodeError(e.to_string()))?; if let Some(value) = args.insertable { insert_struct = Some(value.to_string()); } } - Ok(Self { inner, insert_struct, pkey }) + Ok(Self { + inner, + insert_struct, + pkey, + }) } } @@ -85,17 +87,20 @@ impl std::ops::Deref for ModelMetadata { #[cfg(test)] mod tests { - use syn::ItemStruct; use super::*; + use syn::ItemStruct; #[test] fn test_decode_metadata() { - let ast = syn::parse_str::(r#"struct User { + let ast = syn::parse_str::( + r#"struct User { #[ormlite(column = "Id")] id: i32, - }"#).unwrap(); + }"#, + ) + .unwrap(); let input = DeriveInput::from(ast); let meta = ModelMetadata::from_derive(&input).unwrap(); assert_eq!(meta.pkey.column_name, "Id"); } -} \ No newline at end of file +} diff --git a/attr/src/metadata/table.rs b/attr/src/metadata/table.rs index 5dadc267..3c012a45 100644 --- a/attr/src/metadata/table.rs +++ b/attr/src/metadata/table.rs @@ -1,8 +1,8 @@ -use convert_case::{Case, Casing}; -use syn::DeriveInput; use crate::ident::Ident; use crate::metadata::column::ColumnMetadata; use crate::{DeriveInputExt, ModelAttributes, SyndecodeError}; +use convert_case::{Case, Casing}; +use syn::DeriveInput; /// Metadata used for IntoArguments, TableMeta, and (subset of) Model /// This structs are constructed from the *Attribute structs in crate::attr. @@ -34,8 +34,7 @@ impl TableMetadata { let struct_name = Ident::from(&ast.ident); let mut table_name = None; for attr in ast.attrs.iter().filter(|a| a.path().is_ident("ormlite")) { - let args: ModelAttributes = attr.parse_args() - .map_err(|e| SyndecodeError(e.to_string()))?; + let args: ModelAttributes = attr.parse_args().map_err(|e| SyndecodeError(e.to_string()))?; if let Some(value) = args.table { table_name = Some(value.value()); } @@ -44,17 +43,19 @@ impl TableMetadata { } } let table_name = table_name.unwrap_or_else(|| struct_name.to_string().to_case(Case::Snake)); - let mut columns = ast.fields() + let mut columns = ast + .fields() .map(ColumnMetadata::try_from) - .collect::, _>>().unwrap(); + .collect::, _>>() + .unwrap(); let mut pkey = columns .iter() - .find(|&c| c.marked_primary_key).map(|c| c.clone()) + .find(|&c| c.marked_primary_key) + .map(|c| c.clone()) .map(|c| c.column_name.clone()); if pkey.is_none() { let candidates = sqlmo::util::pkey_column_names(&table_name); - let c = columns.iter_mut() - .find(|c| candidates.contains(c.identifier.as_ref())); + let c = columns.iter_mut().find(|c| candidates.contains(c.identifier.as_ref())); if let Some(c) = c { c.has_database_default = true; pkey = Some(c.column_name.clone()); @@ -69,18 +70,15 @@ impl TableMetadata { }) } - pub fn all_fields(&self) -> impl Iterator + '_ { - self.columns.iter() - .map(|c| &c.identifier) + pub fn all_fields(&self) -> impl Iterator + '_ { + self.columns.iter().map(|c| &c.identifier) } - pub fn database_columns(&self) -> impl Iterator + '_ { - self.columns.iter() - .filter(|&c| !c.skip) + pub fn database_columns(&self) -> impl Iterator + '_ { + self.columns.iter().filter(|&c| !c.skip) } - pub fn many_to_one_joins(&self) -> impl Iterator + '_ { - self.columns.iter() - .filter(|&c| c.many_to_one_column_name.is_some()) + pub fn many_to_one_joins(&self) -> impl Iterator + '_ { + self.columns.iter().filter(|&c| c.many_to_one_column_name.is_some()) } } diff --git a/attr/src/repr.rs b/attr/src/repr.rs index 2bbf9910..9f88911a 100644 --- a/attr/src/repr.rs +++ b/attr/src/repr.rs @@ -3,10 +3,7 @@ use structmeta::StructMeta; use syn::Path; #[derive(StructMeta)] -pub struct Repr( - #[struct_meta(unnamed)] - Path, -); +pub struct Repr(#[struct_meta(unnamed)] Path); impl std::fmt::Debug for Repr { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -31,7 +28,9 @@ impl Repr { pub fn from_attributes(attrs: &[syn::Attribute]) -> Option { for a in attrs { - let Some(ident) = a.path().get_ident() else { continue; }; + let Some(ident) = a.path().get_ident() else { + continue; + }; if ident == Self::ATTRIBUTE { // semantically, the parse error and returning Some are different, // so we're writing out Some() instead of using `.ok()` @@ -40,4 +39,4 @@ impl Repr { } None } -} \ No newline at end of file +} diff --git a/attr/src/ttype.rs b/attr/src/ttype.rs index 7d651cb3..aade52ae 100644 --- a/attr/src/ttype.rs +++ b/attr/src/ttype.rs @@ -1,7 +1,7 @@ +use crate::ident::Ident; use proc_macro2::TokenStream; use quote::TokenStreamExt; use syn::PathArguments; -use crate::ident::Ident; /// Token type. A rust AST token, representing a type. #[derive(Clone, Debug, PartialEq, Hash)] @@ -167,11 +167,7 @@ impl From<&syn::Path> for InnerType { }; let mut path = path.segments.iter().map(|s| Ident::from(&s.ident)).collect::>(); let ident = path.pop().expect("path must have at least one segment"); - InnerType { - path, - args, - ident, - } + InnerType { path, args, ident } } } @@ -188,7 +184,6 @@ impl quote::ToTokens for InnerType { } } - #[cfg(test)] mod tests { use super::*; diff --git a/cli/src/command.rs b/cli/src/command.rs index 072bfc7f..d0ae5865 100644 --- a/cli/src/command.rs +++ b/cli/src/command.rs @@ -1,9 +1,9 @@ -mod migrate; -mod up; mod down; mod init; +mod migrate; +mod up; +pub use down::*; +pub use init::*; pub use migrate::*; pub use up::*; -pub use down::*; -pub use init::*; \ No newline at end of file diff --git a/cli/src/command/down.rs b/cli/src/command/down.rs index 599762a4..26199fbd 100644 --- a/cli/src/command/down.rs +++ b/cli/src/command/down.rs @@ -1,16 +1,16 @@ use std::env::var; use std::fs; -use std::path::Path; use anyhow::{Error, Result}; use clap::Parser; +use std::path::Path; -use ormlite::postgres::{PgArguments, PgConnection}; -use ormlite::{Acquire, Connection, Executor}; use crate::command::{get_executed_migrations, get_pending_migrations, MigrationType}; -use ormlite_core::config::{get_var_snapshot_folder, get_var_database_url, get_var_migration_folder}; -use crate::util::{CommandSuccess, create_runtime}; +use crate::util::{create_runtime, CommandSuccess}; +use ormlite::postgres::{PgArguments, PgConnection}; use ormlite::Arguments; +use ormlite::{Acquire, Connection, Executor}; +use ormlite_core::config::{get_var_database_url, get_var_migration_folder, get_var_snapshot_folder}; use url::Url; #[derive(Parser, Debug)] @@ -71,7 +71,9 @@ impl Down { } else if executed.len() == 1 { "0_empty".to_string() } else { - return Err(Error::msg("No target migration was specified and there are no migrations to rollback to.")); + return Err(Error::msg( + "No target migration was specified and there are no migrations to rollback to.", + )); }; let snapshot_folder = get_var_snapshot_folder(); @@ -79,18 +81,26 @@ impl Down { let Some(backup) = backups.iter().find(|b| { if target.chars().all(|c| c.is_numeric()) { b.split_once('_').map(|(version, _)| version == target).unwrap_or(false) - } else if target.chars().next().map(|c| c.is_numeric()).unwrap_or(false) && target.contains('_') { // my_description + } else if target.chars().next().map(|c| c.is_numeric()).unwrap_or(false) && target.contains('_') { + // my_description **b == format!("{target}.sql.bak") } else { b.split_once('_').map(|(_, desc)| desc == target).unwrap_or(false) } }) else { - return Err(Error::msg(format!("Looked for snapshot `{}` in {}, but could not find it.", target, snapshot_folder.display()))); + return Err(Error::msg(format!( + "Looked for snapshot `{}` in {}, but could not find it.", + target, + snapshot_folder.display() + ))); }; if !self.force { - println!("Re-run with -f to execute rollback. This command will restore the following snapshot:\n{}", snapshot_folder.join(backup).display()); - return Ok(()) + println!( + "Re-run with -f to execute rollback. This command will restore the following snapshot:\n{}", + snapshot_folder.join(backup).display() + ); + return Ok(()); } let mut user = Url::parse(&url)?.username().to_string(); @@ -107,16 +117,21 @@ impl Down { .ok_or("Failed to restore database.")?; } else { if let Some(target) = self.target { - executed = executed.into_iter().take_while(|m| { - let matches = if target.chars().all(|c| c.is_numeric()) { - m.version_str() == target - } else if target.chars().next().map(|c| c.is_numeric()).unwrap_or(false) && target.contains('_') { // my_description - m.name == target - } else { - m.description == target - }; - !matches - }).collect(); + executed = executed + .into_iter() + .take_while(|m| { + let matches = if target.chars().all(|c| c.is_numeric()) { + m.version_str() == target + } else if target.chars().next().map(|c| c.is_numeric()).unwrap_or(false) && target.contains('_') + { + // my_description + m.name == target + } else { + m.description == target + }; + !matches + }) + .collect(); } else { executed.truncate(1); } @@ -140,4 +155,4 @@ impl Down { } Ok(()) } -} \ No newline at end of file +} diff --git a/cli/src/command/init.rs b/cli/src/command/init.rs index 7ec77b6b..8c46a88e 100644 --- a/cli/src/command/init.rs +++ b/cli/src/command/init.rs @@ -3,12 +3,11 @@ use clap::Parser; use colored::Colorize; use ormlite::{Acquire, Connection}; - -use ormlite::Executor; use ormlite::postgres::PgConnection; +use ormlite::Executor; -use ormlite_core::config::{get_var_database_url}; -use crate::util::{create_runtime}; +use crate::util::create_runtime; +use ormlite_core::config::get_var_database_url; const INIT_QUERY: &str = r#" CREATE TABLE public._sqlx_migrations ( @@ -33,7 +32,11 @@ impl Init { let conn = conn.acquire().await?; let table_exists = conn.execute("select 1 from _sqlx_migrations limit 1").await.is_ok(); if table_exists { - eprintln!("{} Database {} already initialized. No actions taken.", "SUCCESS".green(), url); + eprintln!( + "{} Database {} already initialized. No actions taken.", + "SUCCESS".green(), + url + ); return Ok(()); } conn.execute(INIT_QUERY).await?; @@ -41,4 +44,4 @@ impl Init { Ok(()) }) } -} \ No newline at end of file +} diff --git a/cli/src/command/migrate.rs b/cli/src/command/migrate.rs index 7d3e7574..963c2b3b 100644 --- a/cli/src/command/migrate.rs +++ b/cli/src/command/migrate.rs @@ -5,15 +5,15 @@ use std::path::Path; use anyhow::{anyhow, Context, Error, Result}; use clap::Parser; -use sqlmo::{Dialect, migrate::Statement, Migration, Schema, ToSql}; +use sqlmo::{migrate::Statement, Dialect, Migration, Schema, ToSql}; use sqlmo_sqlx::FromPostgres; use time::macros::format_description; use time::OffsetDateTime as DateTime; use tokio::runtime::Runtime; -use ormlite::{Acquire, Connection}; use ormlite::postgres::PgConnection; use ormlite::Row; +use ormlite::{Acquire, Connection}; use ormlite_core::config; use ormlite_core::config::get_var_model_folders; use ormlite_core::schema::TryFromOrmlite; @@ -97,31 +97,31 @@ pub struct Migrate { pub(crate) verbose: bool, } - fn create_migration(folder: &Path, file_name: String, migration: MigrationType, content: &str) -> Result<()> { let file_path = folder.join(file_name).with_extension(migration.extension()); let mut file = File::create(&file_path).context("Failed to create file")?; - file.write_all(content.as_bytes()) - .context("Could not write to file")?; + file.write_all(content.as_bytes()).context("Could not write to file")?; eprintln!("{}: Created migration", file_path.display()); Ok(()) } /// Migrations are sorted asc. Last is most recent. pub async fn get_executed_migrations(conn: &mut PgConnection) -> Result> { - let migrations = ormlite::query(GET_MIGRATIONS_QUERY) - .fetch_all(conn).await?; - let migrations = migrations.into_iter().map(|m: ormlite::postgres::PgRow| { - let name: String = m.get("name"); - let version: i64 = m.get("version"); - let description: String = m.get("description"); - MigrationMetadata { - name: name.to_string(), - version, - description, - } - }).collect(); + let migrations = ormlite::query(GET_MIGRATIONS_QUERY).fetch_all(conn).await?; + let migrations = migrations + .into_iter() + .map(|m: ormlite::postgres::PgRow| { + let name: String = m.get("name"); + let version: i64 = m.get("version"); + let description: String = m.get("description"); + MigrationMetadata { + name: name.to_string(), + version, + description, + } + }) + .collect(); Ok(migrations) } @@ -141,18 +141,25 @@ pub fn get_pending_migrations(folder: &Path) -> Result> { version, description, }) - }).collect::, _>>()?; + }) + .collect::, _>>()?; migrations.sort(); Ok(migrations) } // Returns the type of migration environment, either None (any), Simple, or Up (it doesn't return Down) -fn check_for_pending_migrations(folder: &Path, runtime: &Runtime, conn: &mut PgConnection) -> Result> { +fn check_for_pending_migrations( + folder: &Path, + runtime: &Runtime, + conn: &mut PgConnection, +) -> Result> { let executed = runtime.block_on(get_executed_migrations(conn))?; let pending = get_pending_migrations(folder)?; if executed.len() < pending.len() { - return Err(anyhow!("Pending migrations are not in sync with the database. Please run `ormlite up` first.")); + return Err(anyhow!( + "Pending migrations are not in sync with the database. Please run `ormlite up` first." + )); } for (executed, pending) in executed.iter().zip(pending.iter()) { if executed != pending { @@ -192,21 +199,28 @@ fn experimental_modifications_to_schema(schema: &mut Schema) -> Result<()> { Ok(()) } -fn autogenerate_migration(codebase_path: &[&Path], runtime: &Runtime, conn: &mut PgConnection, opts: &Migrate) -> Result { +fn autogenerate_migration( + codebase_path: &[&Path], + runtime: &Runtime, + conn: &mut PgConnection, + opts: &Migrate, +) -> Result { let mut current = runtime.block_on(Schema::try_from_postgres(conn, "public"))?; current.tables.retain(|t| t.name != "_sqlx_migrations"); let mut desired = Schema::try_from_ormlite_project(codebase_path)?; experimental_modifications_to_schema(&mut desired)?; - let migration = current.migrate_to(desired, &sqlmo::MigrationOptions { - debug: opts.verbose, - allow_destructive: false, - })?; + let migration = current.migrate_to( + desired, + &sqlmo::MigrationOptions { + debug: opts.verbose, + allow_destructive: false, + }, + )?; Ok(migration) } - impl Migrate { pub fn run(self) -> Result<()> { let runtime = create_runtime(); @@ -229,7 +243,7 @@ impl Migrate { let migration = autogenerate_migration(&folder_paths, &runtime, conn, &self)?; for d in &migration.debug_results { - tracing::debug!(table=d.table_name(), "Table is identical"); + tracing::debug!(table = d.table_name(), "Table is identical"); } if self.dry { @@ -247,12 +261,16 @@ impl Migrate { let mut file_name = dt.format(format_description!("[year][month][day][hour][minute][second]"))?; file_name.push('_'); file_name.push_str(&self.name); - let migration_body = migration.as_ref().map(|m| { - m.statements.iter() - .map(|s| s.to_sql(Dialect::Postgres) + ";") - .collect::>() - .join("\n") - }).unwrap_or_default(); + let migration_body = migration + .as_ref() + .map(|m| { + m.statements + .iter() + .map(|s| s.to_sql(Dialect::Postgres) + ";") + .collect::>() + .join("\n") + }) + .unwrap_or_default(); if self.reversible { create_migration(&folder, file_name.clone(), MigrationType::Up, &migration_body)?; create_migration(&folder, file_name.clone(), MigrationType::Down, "")?; @@ -266,8 +284,18 @@ impl Migrate { println!("It auto-generated the following actions:"); for statement in &migration.statements { match statement { - Statement::CreateTable(s) => println!("Create table {} with columns: {}", &s.name, s.columns.iter().map(|c| c.name.to_string()).collect::>().join(", ")), - Statement::CreateIndex(s) => println!("Create index {} on {}", &s.name, &s.table), + Statement::CreateTable(s) => println!( + "Create table {} with columns: {}", + &s.name, + s.columns + .iter() + .map(|c| c.name.to_string()) + .collect::>() + .join(", ") + ), + Statement::CreateIndex(s) => { + println!("Create index {} on {}", &s.name, &s.table) + } Statement::AlterTable(s) => println!("Alter table {}", &s.name), Statement::Update(s) => println!("Update table {}", &s.table), Statement::DropTable(s) => println!("Drop table {}", &s.name), @@ -277,4 +305,4 @@ impl Migrate { } Ok(()) } -} \ No newline at end of file +} diff --git a/cli/src/command/up.rs b/cli/src/command/up.rs index 5b8d6efa..b7a06bdf 100644 --- a/cli/src/command/up.rs +++ b/cli/src/command/up.rs @@ -1,15 +1,15 @@ -use std::collections::HashSet; -use std::fs; -use std::fs::File; -use std::time::Instant; +use crate::command::{get_executed_migrations, get_pending_migrations, MigrationType}; +use crate::util::{create_runtime, CommandSuccess}; use anyhow::{anyhow, Result}; use clap::Parser; -use ormlite::{Executor, Arguments, Acquire, Connection}; use ormlite::postgres::{PgArguments, PgConnection}; -use crate::command::{get_executed_migrations, get_pending_migrations, MigrationType}; -use ormlite_core::config::{get_var_snapshot_folder, get_var_database_url, get_var_migration_folder}; -use crate::util::{CommandSuccess, create_runtime}; +use ormlite::{Acquire, Arguments, Connection, Executor}; +use ormlite_core::config::{get_var_database_url, get_var_migration_folder, get_var_snapshot_folder}; use sha2::{Digest, Sha384}; +use std::collections::HashSet; +use std::fs; +use std::fs::File; +use std::time::Instant; use tracing::debug; #[derive(Parser, Debug)] @@ -36,7 +36,8 @@ impl Up { let conn = runtime.block_on(conn.acquire()).unwrap(); let executed = runtime.block_on(get_executed_migrations(conn))?; - let pending = get_pending_migrations(&folder).unwrap() + let pending = get_pending_migrations(&folder) + .unwrap() .into_iter() .filter(|m| m.migration_type() != MigrationType::Down) .collect::>(); @@ -62,7 +63,10 @@ impl Up { let last_executed = executed.last().map(|m| m.name.clone()).unwrap_or("0_empty".to_string()); let executed = executed.into_iter().map(|m| m.version).collect::>(); - let pending = pending.into_iter().filter(|m| !executed.contains(&m.version)).collect::>(); + let pending = pending + .into_iter() + .filter(|m| !executed.contains(&m.version)) + .collect::>(); let is_simple = pending.last().as_ref().unwrap().migration_type() == MigrationType::Simple; if (is_simple && !self.no_snapshot) || (!is_simple && self.snapshot) { @@ -82,7 +86,9 @@ impl Up { let pending = pending.iter().take(if self.all { pending.len() } else { 1 }); for migration in pending { debug!("Running migration: {}", migration.name); - let file_path = folder.join(&migration.name).with_extension(migration.migration_type().extension()); + let file_path = folder + .join(&migration.name) + .with_extension(migration.migration_type().extension()); let body = fs::read_to_string(&file_path)?; let checksum = Sha384::digest(body.as_bytes()).to_vec(); diff --git a/cli/src/main.rs b/cli/src/main.rs index 68c61694..d255e578 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -1,5 +1,5 @@ -use clap::{Parser, Subcommand}; use anyhow::Result; +use clap::{Parser, Subcommand}; use tracing::Level; use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::util::SubscriberInitExt; @@ -9,7 +9,6 @@ mod util; use command::*; - #[derive(Parser, Debug)] #[command(author, version, about)] struct Cli { @@ -36,13 +35,12 @@ fn main() -> Result<()> { let cli = Cli::parse(); let level = if cli.verbose { Level::DEBUG } else { Level::INFO }; tracing_subscriber::registry() - .with(tracing_subscriber::fmt::layer() - .without_time() - ) - .with(tracing_subscriber::filter::Targets::new() - .with_target(env!("CARGO_BIN_NAME"), level) - .with_target("ormlite_attr", level) - .with_target("sqlmo", level) + .with(tracing_subscriber::fmt::layer().without_time()) + .with( + tracing_subscriber::filter::Targets::new() + .with_target(env!("CARGO_BIN_NAME"), level) + .with_target("ormlite_attr", level) + .with_target("sqlmo", level), ) .init(); use Command::*; @@ -52,4 +50,4 @@ fn main() -> Result<()> { Down(down) => down.run(), Init(init) => init.run(), } -} \ No newline at end of file +} diff --git a/cli/src/util.rs b/cli/src/util.rs index 2c921f34..bee59883 100644 --- a/cli/src/util.rs +++ b/cli/src/util.rs @@ -31,4 +31,4 @@ impl CommandSuccess for std::process::Output { Err(Error::msg(message.to_string())) } } -} \ No newline at end of file +} diff --git a/core/src/config.rs b/core/src/config.rs index cb8526d3..fdd01e63 100644 --- a/core/src/config.rs +++ b/core/src/config.rs @@ -21,8 +21,7 @@ pub fn get_var_database_url() -> String { var("DATABASE_URL").expect("DATABASE_URL must be set") } - pub fn get_var_model_folders() -> Vec { let folders = var("MODEL_FOLDERS").unwrap_or_else(|_| MODEL_FOLDERS.to_string()); folders.split(',').map(|s| PathBuf::from_str(s).unwrap()).collect() -} \ No newline at end of file +} diff --git a/core/src/error.rs b/core/src/error.rs index 03e83b88..1b213796 100644 --- a/core/src/error.rs +++ b/core/src/error.rs @@ -10,4 +10,4 @@ pub enum Error { #[error("{0}")] OrmliteError(String), -} \ No newline at end of file +} diff --git a/core/src/insert.rs b/core/src/insert.rs index 3c8fb87e..7fda7e89 100644 --- a/core/src/insert.rs +++ b/core/src/insert.rs @@ -1,8 +1,8 @@ +use crate::Result; use futures::future::BoxFuture; -#[allow(unused_imports)] -use sqlmo::{Insert, Dialect, ToSql}; pub use sqlmo::query::OnConflict; -use crate::Result; +#[allow(unused_imports)] +use sqlmo::{Dialect, Insert, ToSql}; /// Represents an insert query. /// We had to turn this into a model because we need to pass in the on_conflict configuration. @@ -14,7 +14,6 @@ pub struct Insertion<'a, Acquire, Model, DB: sqlx::Database> { pub _db: std::marker::PhantomData, } - impl<'a, Acquire, Model, DB: sqlx::Database> Insertion<'a, Acquire, Model, DB> { pub fn on_conflict(mut self, c: OnConflict) -> Self { self.insert.on_conflict = c; @@ -22,7 +21,9 @@ impl<'a, Acquire, Model, DB: sqlx::Database> Insertion<'a, Acquire, Model, DB> { } } -impl<'a, Acquire, Model: crate::model::Model, DB: sqlx::Database> std::future::IntoFuture for Insertion<'a, Acquire, Model, DB> { +impl<'a, Acquire, Model: crate::model::Model, DB: sqlx::Database> std::future::IntoFuture + for Insertion<'a, Acquire, Model, DB> +{ type Output = Result; type IntoFuture = BoxFuture<'a, Self::Output>; diff --git a/core/src/join.rs b/core/src/join.rs index 7f3100e0..2731d9c5 100644 --- a/core/src/join.rs +++ b/core/src/join.rs @@ -1,10 +1,10 @@ -use std::ops::{Deref, DerefMut}; +use crate::model::Model; use async_trait::async_trait; use serde::{Serialize, Serializer}; -use sqlmo::query::{Join as JoinQueryFragment}; +use sqlmo::query::Join as JoinQueryFragment; use sqlmo::query::SelectColumn; use sqlx::{Database, Decode, Encode, Type}; -use crate::model::Model; +use std::ops::{Deref, DerefMut}; pub trait JoinMeta { type IdType: Clone + Send + Eq + PartialEq + std::hash::Hash; @@ -30,9 +30,9 @@ impl JoinMeta for Join { #[async_trait] pub trait Loadable { async fn load<'s, 'e, E>(&'s mut self, db: E) -> crate::error::Result<&'s T> - where - T::IdType: 'e + Send + Sync, - E: 'e + sqlx::Executor<'e, Database=DB>; + where + T::IdType: 'e + Send + Sync, + E: 'e + sqlx::Executor<'e, Database = DB>; } #[derive(Debug)] @@ -49,7 +49,6 @@ pub enum JoinData { Modified(T), } - impl Join { pub fn new_with_id(id: T::IdType) -> Self { Self { @@ -89,15 +88,15 @@ impl Join { match owned { JoinData::NotQueried => None, JoinData::QueryResult(_) => None, - JoinData::Modified(obj) => { - Some(obj) - } + JoinData::Modified(obj) => Some(obj), } } fn transition_to_modified(&mut self) -> &mut T { let owned = std::mem::replace(&mut self.data, JoinData::NotQueried); match owned { - JoinData::NotQueried => panic!("Tried to deref_mut a joined object, but it has not been queried."), + JoinData::NotQueried => { + panic!("Tried to deref_mut a joined object, but it has not been queried.") + } JoinData::QueryResult(r) => { self.data = JoinData::Modified(r); } @@ -122,14 +121,17 @@ impl Join { #[async_trait] impl Loadable for Join - where - DB: Database, - T: JoinMeta + Model + Send, - T::IdType: for<'a> Encode<'a, DB> + for<'a> Decode<'a, DB> + Type, +where + DB: Database, + T: JoinMeta + Model + Send, + T::IdType: for<'a> Encode<'a, DB> + for<'a> Decode<'a, DB> + Type, { - async fn load<'s, 'e, E: sqlx::Executor<'e, Database=DB> + 'e>(&'s mut self, conn: E) -> crate::error::Result<&'s T> - where - T::IdType: 'e + Send + Sync, + async fn load<'s, 'e, E: sqlx::Executor<'e, Database = DB> + 'e>( + &'s mut self, + conn: E, + ) -> crate::error::Result<&'s T> + where + T::IdType: 'e + Send + Sync, { let model = T::fetch_one(self.id.clone(), conn).await?; self.data = JoinData::QueryResult(model); @@ -143,7 +145,9 @@ impl Deref for Join { fn deref(&self) -> &Self::Target { match &self.data { - JoinData::NotQueried => panic!("Tried to deref a joined object, but it has not been queried."), + JoinData::NotQueried => { + panic!("Tried to deref a joined object, but it has not been queried.") + } JoinData::QueryResult(r) => r, JoinData::Modified(r) => r, } @@ -194,15 +198,13 @@ impl JoinDescription { unimplemented!() } }; - JoinQueryFragment::new(table) - .alias(self.relation) - .on_raw(join) + JoinQueryFragment::new(table).alias(self.relation).on_raw(join) } - pub fn select_clause(&self) -> impl Iterator + '_ { - self.joined_columns.iter() - .map(|c| SelectColumn::table_column(self.relation, c) - .alias(self.alias(c))) + pub fn select_clause(&self) -> impl Iterator + '_ { + self.joined_columns + .iter() + .map(|c| SelectColumn::table_column(self.relation, c).alias(self.alias(c))) } pub fn alias(&self, column: &str) -> String { @@ -213,11 +215,12 @@ impl JoinDescription { impl Serialize for Join { fn serialize(&self, serializer: S) -> Result where - S: Serializer { - match &self.data { - JoinData::Modified(data) => data.serialize(serializer), - JoinData::NotQueried => serializer.serialize_none(), - JoinData::QueryResult(data) => data.serialize(serializer), - } + S: Serializer, + { + match &self.data { + JoinData::Modified(data) => data.serialize(serializer), + JoinData::NotQueried => serializer.serialize_none(), + JoinData::QueryResult(data) => data.serialize(serializer), + } } -} \ No newline at end of file +} diff --git a/core/src/lib.rs b/core/src/lib.rs index ab9bba9f..f48aee36 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -3,11 +3,10 @@ pub use self::query_builder::SelectQueryBuilder; pub use futures::future::BoxFuture; pub use join::Join; -mod error; pub mod config; +mod error; +pub mod insert; +pub mod join; pub mod model; pub mod query_builder; -pub mod join; -pub mod insert; pub mod schema; - diff --git a/core/src/model.rs b/core/src/model.rs index df2f3bbe..06c047e9 100644 --- a/core/src/model.rs +++ b/core/src/model.rs @@ -26,31 +26,31 @@ use futures::future::BoxFuture; /// age: i32, /// } pub trait Insertable - where - Self: Sized + Send + Sync, - DB: sqlx::Database, +where + Self: Sized + Send + Sync, + DB: sqlx::Database, { type Model; fn insert<'e, A>(self, conn: A) -> BoxFuture<'e, Result> - where - A: 'e + Send + sqlx::Acquire<'e, Database=DB>; + where + A: 'e + Send + sqlx::Acquire<'e, Database = DB>; } /// A struct that implements `ModelBuilder` implements the builder pattern for a model. pub trait ModelBuilder<'a, DB> - where - Self: Sized + Send + Sync, - DB: sqlx::Database, +where + Self: Sized + Send + Sync, + DB: sqlx::Database, { type Model; fn insert<'e: 'a, E>(self, db: E) -> BoxFuture<'a, Result> - where - E: 'e + sqlx::Executor<'e, Database=DB>; + where + E: 'e + sqlx::Executor<'e, Database = DB>; fn update<'e: 'a, E>(self, db: E) -> BoxFuture<'a, Result> - where - E: 'e + sqlx::Executor<'e, Database=DB>; + where + E: 'e + sqlx::Executor<'e, Database = DB>; /// All fields that will be modified in the query. fn modified_fields(&self) -> Vec<&'static str>; @@ -60,9 +60,9 @@ pub trait ModelBuilder<'a, DB> } pub trait HasModelBuilder<'slf, DB> - where - DB: sqlx::Database, - Self: Sized + TableMeta, +where + DB: sqlx::Database, + Self: Sized + TableMeta, { type ModelBuilder: ModelBuilder<'slf, DB>; @@ -75,37 +75,35 @@ pub trait HasModelBuilder<'slf, DB> /// The core trait. a struct that implements `Model` can also implement `HasModelBuilder`, (and is required to implement `Insertable`) pub trait Model - where - DB: sqlx::Database, - Self: Sized + TableMeta, +where + DB: sqlx::Database, + Self: Sized + TableMeta, { /// Insert the model into the database. fn insert<'a, A>(self, conn: A) -> crate::insert::Insertion<'a, A, Self, DB> - where - A: 'a + Send + sqlx::Acquire<'a, Database=DB>, - Self: Send; + where + A: 'a + Send + sqlx::Acquire<'a, Database = DB>, + Self: Send; /// `Model` objects can't track what fields are updated, so this method will update all fields. /// If you want to update only some fields, use `update_partial` instead. fn update_all_fields<'e, E>(self, db: E) -> BoxFuture<'e, Result> - where - E: 'e + Send + sqlx::Executor<'e, Database=DB>; + where + E: 'e + Send + sqlx::Executor<'e, Database = DB>; fn delete<'e, E>(self, db: E) -> BoxFuture<'e, Result<()>> - where - E: 'e + sqlx::Executor<'e, Database=DB>; + where + E: 'e + sqlx::Executor<'e, Database = DB>; /// Get by primary key. fn fetch_one<'e, 'a, Arg, E>(id: Arg, db: E) -> BoxFuture<'e, Result> - where - 'a: 'e, - E: 'e + sqlx::Executor<'e, Database=DB>, - Arg: 'a + Send + sqlx::Encode<'a, DB> + sqlx::Type; + where + 'a: 'e, + E: 'e + sqlx::Executor<'e, Database = DB>, + Arg: 'a + Send + sqlx::Encode<'a, DB> + sqlx::Type; /// If query building isn't meeting your needs, use this method to query the table using raw SQL. - fn query( - query: &str, - ) -> sqlx::query::QueryAs::Arguments>; + fn query(query: &str) -> sqlx::query::QueryAs::Arguments>; /// Create a `SelectQueryBuilder` to build a query. fn select<'args>() -> SelectQueryBuilder<'args, DB, Self>; diff --git a/core/src/query_builder/args.rs b/core/src/query_builder/args.rs index e0d54e90..059c277a 100644 --- a/core/src/query_builder/args.rs +++ b/core/src/query_builder/args.rs @@ -2,10 +2,7 @@ use core::default::Default; use sqlx::database::HasArguments; use sqlx::{Arguments, Database, IntoArguments}; -pub struct QueryBuilderArgs<'q, DB: Database>( - pub Box<>::Arguments>, - usize, -); +pub struct QueryBuilderArgs<'q, DB: Database>(pub Box<>::Arguments>, usize); impl<'q, DB: Database> QueryBuilderArgs<'q, DB> { pub fn add + sqlx::Type>(&mut self, arg: T) { diff --git a/core/src/query_builder/mod.rs b/core/src/query_builder/mod.rs index 6e05b7eb..241e3e92 100644 --- a/core/src/query_builder/mod.rs +++ b/core/src/query_builder/mod.rs @@ -2,6 +2,6 @@ pub mod args; pub mod placeholder; mod select; mod util; +pub use args::QueryBuilderArgs; pub use placeholder::Placeholder; pub use select::SelectQueryBuilder; -pub use args::QueryBuilderArgs; diff --git a/core/src/query_builder/select.rs b/core/src/query_builder/select.rs index 6cc13431..98f33950 100644 --- a/core/src/query_builder/select.rs +++ b/core/src/query_builder/select.rs @@ -1,19 +1,18 @@ use crate::error::{Error, Result}; +use crate::model::Model; use crate::query_builder::args::QueryBuilderArgs; use crate::query_builder::{util, Placeholder}; -use crate::model::Model; use sqlmo::ToSql; use sqlx::database::HasArguments; +use crate::join::JoinDescription; +use sqlmo::{query::Where, Select}; use sqlx::{Executor, IntoArguments}; use std::marker::PhantomData; -use crate::join::JoinDescription; -use sqlmo::{Select, query::Where}; pub use sqlmo::query::Direction; - // Add additional information to the sqlx::Database pub trait DatabaseMetadata { fn dialect() -> sqlmo::Dialect; @@ -129,8 +128,8 @@ where /// Convenience method to add a `WHERE` and bind a value in one call. pub fn where_bind(mut self, clause: &'static str, value: T) -> Self - where - T: 'args + Send + sqlx::Type + sqlx::Encode<'args, DB>, + where + T: 'args + Send + sqlx::Type + sqlx::Encode<'args, DB>, { self.query = self.query.where_raw(clause); self.arguments.add(value); @@ -230,11 +229,10 @@ where impl<'args, DB: sqlx::Database + DatabaseMetadata, M: Model> Default for SelectQueryBuilder<'args, DB, M> { fn default() -> Self { Self { - query: Select::default() - .from(M::table_name()), + query: Select::default().from(M::table_name()), arguments: QueryBuilderArgs::default(), model: PhantomData, gen: DB::placeholder(), } } -} \ No newline at end of file +} diff --git a/core/src/query_builder/util.rs b/core/src/query_builder/util.rs index 8fa99193..2cb57412 100644 --- a/core/src/query_builder/util.rs +++ b/core/src/query_builder/util.rs @@ -1,7 +1,7 @@ use crate::query_builder::args::QueryBuilderArgs; use crate::{Error, Result}; use sqlparser::dialect::GenericDialect; -use sqlparser::tokenizer::{Tokenizer, Token}; +use sqlparser::tokenizer::{Token, Tokenizer}; use sqlx::query::QueryAs; pub fn replace_placeholders>( @@ -22,35 +22,36 @@ pub fn replace_placeholders>( buf.push_str(&placeholder_generator.next().unwrap()); placeholder_count += 1; } - Token::Char(c) => match c { - '?' => { - buf.push_str(&placeholder_generator.next().unwrap()); - placeholder_count += 1; - } - '$' => { - let next_tok = it.next(); - if let Some(next_tok) = next_tok { - match next_tok { - Token::Number(text, _) => { - let n = text.parse::().map_err(|_| Error::OrmliteError( + Token::Char(c) => { + match c { + '?' => { + buf.push_str(&placeholder_generator.next().unwrap()); + placeholder_count += 1; + } + '$' => { + let next_tok = it.next(); + if let Some(next_tok) = next_tok { + match next_tok { + Token::Number(text, _) => { + let n = text.parse::().map_err(|_| Error::OrmliteError( format!("Failed to parse number after a $ during query tokenization. Value was: {text}" )))?; - buf.push_str(&format!("${next_tok}")); - placeholder_count = std::cmp::max(placeholder_count, n); + buf.push_str(&format!("${next_tok}")); + placeholder_count = std::cmp::max(placeholder_count, n); + } + _ => {} } - _ => {} } } + _ => buf.push(*c), } - _ => buf.push(*c), - }, + } _ => buf.push_str(&tok.to_string()), } } Ok((buf, placeholder_count)) } - pub(super) fn query_as_with_recast_lifetime<'q, 'r, DB, Model>( s: &'q str, args: QueryBuilderArgs<'r, DB>, @@ -68,14 +69,11 @@ where sqlx::query_as_with(s, recast_args) } - #[cfg(test)] mod tests { use super::*; - - use crate::{Result}; - - + + use crate::Result; #[test] fn test_replace_placeholders() -> Result<()> { @@ -92,12 +90,10 @@ mod tests { #[test] fn test_leave_placeholders_alone() -> Result<()> { let mut placeholder_generator = vec!["$1", "$2", "$3"].into_iter().map(|s| s.to_string()); - let (sql, placeholder_count) = replace_placeholders( - "SELECT * FROM users WHERE email = $1", - &mut placeholder_generator, - )?; + let (sql, placeholder_count) = + replace_placeholders("SELECT * FROM users WHERE email = $1", &mut placeholder_generator)?; assert_eq!(sql, "SELECT * FROM users WHERE email = $1"); assert_eq!(placeholder_count, 1); Ok(()) } -} \ No newline at end of file +} diff --git a/core/src/schema.rs b/core/src/schema.rs index 98df6ca6..fd709896 100644 --- a/core/src/schema.rs +++ b/core/src/schema.rs @@ -1,14 +1,14 @@ use std::collections::BTreeMap; use std::fmt::Formatter; -use std::path::Path; use anyhow::Result; -use sqlmo::{Schema, schema::Column, Table}; -use ormlite_attr::ModelMetadata; use ormlite_attr::schema_from_filepaths; -use ormlite_attr::Ident; use ormlite_attr::ColumnMetadata; +use ormlite_attr::Ident; +use ormlite_attr::ModelMetadata; use ormlite_attr::{InnerType, TType}; +use sqlmo::{schema::Column, Schema, Table}; +use std::path::Path; #[derive(Debug)] pub struct Options { @@ -20,7 +20,9 @@ pub trait TryFromOrmlite: Sized { } trait SqlDiffTableExt { - fn from_metadata(metadata: &ModelMetadata) -> Result where Self: Sized; + fn from_metadata(metadata: &ModelMetadata) -> Result + where + Self: Sized; } impl SqlDiffTableExt for Table { @@ -28,16 +30,20 @@ impl SqlDiffTableExt for Table { Ok(Self { schema: None, name: model.inner.table_name.clone(), - columns: model.inner.columns.iter().map(|c| { - if c.skip { - return Ok(None); - } - let Some(mut col) = Column::from_metadata(c)? else { - return Ok(None); - }; - col.primary_key = model.pkey.column_name == col.name; - Ok(Some(col)) - }) + columns: model + .inner + .columns + .iter() + .map(|c| { + if c.skip { + return Ok(None); + } + let Some(mut col) = Column::from_metadata(c)? else { + return Ok(None); + }; + col.primary_key = model.pkey.column_name == col.name; + Ok(Some(col)) + }) .filter_map(|c| c.transpose()) .collect::, _>>()?, indexes: vec![], @@ -147,10 +153,7 @@ impl SqlType { "Json" => Jsonb, z => Other(z.to_string()), }; - Some(SqlType { - ty, - nullable: false, - }) + Some(SqlType { ty, nullable: false }) } TType::Option(o) => { let inner = Self::from_type(o)?; @@ -159,9 +162,7 @@ impl SqlType { nullable: true, }) } - TType::Join(_) => { - None - } + TType::Join(_) => None, } } } @@ -170,10 +171,14 @@ impl TryFromOrmlite for Schema { fn try_from_ormlite_project(paths: &[&Path]) -> Result { let mut schema = Self::default(); let mut fs_schema = schema_from_filepaths(paths)?; - let primary_key_type: BTreeMap = fs_schema.tables.iter().map(|t| { - let pkey_ty = t.pkey.column_type.inner_type().clone(); - (t.inner.struct_name.to_string(), pkey_ty) - }).collect(); + let primary_key_type: BTreeMap = fs_schema + .tables + .iter() + .map(|t| { + let pkey_ty = t.pkey.column_type.inner_type().clone(); + (t.inner.struct_name.to_string(), pkey_ty) + }) + .collect(); for t in &mut fs_schema.tables { for c in &mut t.inner.columns { // replace alias types with the real type. @@ -184,7 +189,9 @@ impl TryFromOrmlite for Schema { // replace join types with the primary key type. if c.column_type.is_join() { let model_name = c.column_type.inner_type_name(); - let pkey = primary_key_type.get(&model_name).expect(&format!("Could not find model {} for join", model_name)); + let pkey = primary_key_type + .get(&model_name) + .expect(&format!("Could not find model {} for join", model_name)); c.column_type = TType::Inner(pkey.clone()); } } @@ -200,14 +207,13 @@ impl TryFromOrmlite for Schema { #[cfg(test)] mod tests { use super::*; - use syn::parse_str; use assert_matches::assert_matches; use ormlite_attr::TType; use sqlmo::Type; + use syn::parse_str; #[test] fn test_convert_type() -> Result<()> { - let s = TType::from(&parse_str::("String").unwrap()); assert_matches!(SqlType::from_type(&s).unwrap().ty, Type::Text); let s = TType::from(&parse_str::("u32").unwrap()); @@ -226,6 +232,5 @@ mod tests { panic!("Expected array"); }; assert_eq!(*inner, Type::Uuid); - } } diff --git a/macro/src/codegen.rs b/macro/src/codegen.rs index ef333527..b797caef 100644 --- a/macro/src/codegen.rs +++ b/macro/src/codegen.rs @@ -1,20 +1,20 @@ pub mod common; +pub mod from_row; +pub mod insert; +pub mod insert_model; +pub mod into_arguments; +pub mod join_description; +pub mod meta; +pub mod model; +pub mod model_builder; #[cfg(feature = "mysql")] #[cfg_attr(docsrs, doc(cfg(feature = "mysql")))] pub mod mysql; #[cfg(feature = "postgres")] #[cfg_attr(docsrs, doc(cfg(feature = "postgres")))] pub mod postgres; +pub mod select; #[cfg(feature = "sqlite")] #[cfg_attr(docsrs, doc(cfg(feature = "sqlite")))] pub mod sqlite; -pub mod insert; -pub mod into_arguments; -pub mod meta; -pub mod select; -pub mod from_row; -pub mod insert_model; -pub mod join_description; -pub mod model; -pub mod model_builder; pub mod update; diff --git a/macro/src/codegen/common.rs b/macro/src/codegen/common.rs index f8efb181..e769f403 100644 --- a/macro/src/codegen/common.rs +++ b/macro/src/codegen/common.rs @@ -1,15 +1,14 @@ -use std::borrow::Cow; -use ormlite_core::query_builder::Placeholder; -use proc_macro2::TokenStream; -use quote::{quote, ToTokens}; use crate::MetadataCache; use itertools::Itertools; -use ormlite_attr::Ident; use ormlite_attr::ColumnMetadata; +use ormlite_attr::Ident; use ormlite_attr::ModelMetadata; use ormlite_attr::TableMetadata; use ormlite_attr::{InnerType, TType}; - +use ormlite_core::query_builder::Placeholder; +use proc_macro2::TokenStream; +use quote::{quote, ToTokens}; +use std::borrow::Cow; pub fn generate_conditional_bind(c: &ColumnMetadata) -> TokenStream { let name = &c.identifier; @@ -37,13 +36,9 @@ fn ty_is_string(ty: &syn::Type) -> bool { p.path.segments.last().map(|s| s.ident == "String").unwrap_or(false) } - - fn recursive_primitive_types_ty<'a>(ty: &'a TType, cache: &'a MetadataCache) -> Vec> { match ty { - TType::Option(ty) => { - recursive_primitive_types_ty(ty, cache) - } + TType::Option(ty) => recursive_primitive_types_ty(ty, cache), TType::Vec(ty) => { let inner = recursive_primitive_types_ty(ty, cache); let inner = inner.into_iter().next().expect("Vec must have inner type"); @@ -62,18 +57,19 @@ fn recursive_primitive_types_ty<'a>(ty: &'a TType, cache: &'a MetadataCache) -> } } - fn recursive_primitive_types<'a>(table: &'a ModelMetadata, cache: &'a MetadataCache) -> Vec> { - table.inner.columns.iter() - .map(|c| { - recursive_primitive_types_ty(&c.column_type, cache) - }) + table + .inner + .columns + .iter() + .map(|c| recursive_primitive_types_ty(&c.column_type, cache)) .flatten() .collect() } pub(crate) fn table_primitive_types<'a>(attr: &'a TableMetadata, cache: &'a MetadataCache) -> Vec> { - attr.columns.iter() + attr.columns + .iter() .filter(|c| !c.skip) .filter(|c| !c.experimental_encode_as_json) .map(|c| recursive_primitive_types_ty(&c.column_type, cache)) @@ -82,16 +78,18 @@ pub(crate) fn table_primitive_types<'a>(attr: &'a TableMetadata, cache: &'a Meta .collect() } -pub fn from_row_bounds<'a>(db: &dyn OrmliteCodegen, attr: &'a TableMetadata, cache: &'a MetadataCache) -> impl Iterator + 'a { +pub fn from_row_bounds<'a>( + db: &dyn OrmliteCodegen, + attr: &'a TableMetadata, + cache: &'a MetadataCache, +) -> impl Iterator + 'a { let database = db.database_ts(); - table_primitive_types(attr, cache) - .into_iter() - .map(move |ty| { - quote! { - #ty: ::ormlite::decode::Decode<'a, #database>, - #ty: ::ormlite::types::Type<#database>, - } - }) + table_primitive_types(attr, cache).into_iter().map(move |ty| { + quote! { + #ty: ::ormlite::decode::Decode<'a, #database>, + #ty: ::ormlite::types::Type<#database>, + } + }) } fn is_vec(p: &syn::Path) -> bool { @@ -125,5 +123,4 @@ pub trait OrmliteCodegen { // 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; - } diff --git a/macro/src/codegen/from_row.rs b/macro/src/codegen/from_row.rs index 1421f8fa..5383b9a5 100644 --- a/macro/src/codegen/from_row.rs +++ b/macro/src/codegen/from_row.rs @@ -1,10 +1,10 @@ -use proc_macro2::TokenStream; -use quote::quote; -use ormlite_attr::TableMetadata; -use ormlite_attr::Ident; -use ormlite_attr::ColumnMetadata; use crate::codegen::common::{from_row_bounds, OrmliteCodegen}; use crate::MetadataCache; +use ormlite_attr::ColumnMetadata; +use ormlite_attr::Ident; +use ormlite_attr::TableMetadata; +use proc_macro2::TokenStream; +use quote::quote; pub fn impl_FromRow(db: &dyn OrmliteCodegen, attr: &TableMetadata, cache: &MetadataCache) -> TokenStream { let bounds = from_row_bounds(db, attr, cache); @@ -13,14 +13,13 @@ pub fn impl_FromRow(db: &dyn OrmliteCodegen, attr: &TableMetadata, cache: &Metad let prefix_branches = attr.columns.iter().filter(|c| c.is_join()).map(|c| { let name = &c.identifier.to_string(); let iden = &c.identifier; - let meta = cache.get(c.joined_struct_name().unwrap().as_str()) + let meta = cache + .get(c.joined_struct_name().unwrap().as_str()) .expect("Joined struct not found"); let result = if c.is_join_many() { unimplemented!("Join> isn't supported quite yet..."); } else { - let prefixed_columns = meta.database_columns().map(|c| { - format!("__{}__{}", iden, c.identifier) - }); + let prefixed_columns = meta.database_columns().map(|c| format!("__{}__{}", iden, c.identifier)); let path = c.joined_model(); quote! { #path::from_row_using_aliases(row, &[ @@ -37,8 +36,7 @@ pub fn impl_FromRow(db: &dyn OrmliteCodegen, attr: &TableMetadata, cache: &Metad } }); - let field_names = attr.database_columns() - .map(|c| &c.column_name); + let field_names = attr.database_columns().map(|c| &c.column_name); let map_join = if attr.columns.iter().any(|c| c.is_join()) { quote! { @@ -91,13 +89,18 @@ pub fn impl_FromRow(db: &dyn OrmliteCodegen, attr: &TableMetadata, cache: &Metad } } - -pub fn impl_from_row_using_aliases(db: &dyn OrmliteCodegen, 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(db, attr, &metadata_cache); let mut incrementer = 0usize..; - let columns = attr.columns.iter() + let columns = attr + .columns + .iter() .map(|c| { let index = incrementer.next().unwrap(); let get = quote! { aliases[#index] }; @@ -124,7 +127,6 @@ pub fn impl_from_row_using_aliases(db: &dyn OrmliteCodegen, attr: &TableMetadata } } - /// `name` renames the column. Can pass `col.column_name` if it's not renamed. pub fn from_row_for_column(get_value: TokenStream, col: &ColumnMetadata) -> TokenStream { let id = &col.identifier; diff --git a/macro/src/codegen/insert.rs b/macro/src/codegen/insert.rs index 7d4a73e8..f5a8ed1a 100644 --- a/macro/src/codegen/insert.rs +++ b/macro/src/codegen/insert.rs @@ -1,20 +1,23 @@ -use proc_macro2::TokenStream; -use quote::quote; -use ormlite_attr::TableMetadata; -use ormlite_attr::Ident; +use crate::codegen::common::{generate_conditional_bind, insertion_binding, OrmliteCodegen}; +use crate::MetadataCache; use ormlite_attr::ColumnMetadata; +use ormlite_attr::Ident; use ormlite_attr::ModelMetadata; use ormlite_attr::TType; -use crate::codegen::common::{generate_conditional_bind, insertion_binding, OrmliteCodegen}; -use crate::MetadataCache; +use ormlite_attr::TableMetadata; +use proc_macro2::TokenStream; +use quote::quote; -pub fn impl_Model__insert(db: &dyn OrmliteCodegen, attr: &TableMetadata, metadata_cache: &MetadataCache) -> TokenStream { +pub fn impl_Model__insert( + db: &dyn OrmliteCodegen, + attr: &TableMetadata, + metadata_cache: &MetadataCache, +) -> TokenStream { let box_future = crate::util::box_fut_ts(); let mut placeholder = db.placeholder(); let db = db.database_ts(); let table = &attr.table_name; - let params = attr.database_columns() - .map(|_| placeholder.next().unwrap()); + let params = attr.database_columns().map(|_| placeholder.next().unwrap()); let query_bindings = attr.database_columns().map(|c| insertion_binding(c)); @@ -67,15 +70,11 @@ pub fn impl_Model__insert(db: &dyn OrmliteCodegen, attr: &TableMetadata, metadat } } - pub fn impl_ModelBuilder__insert(db: &dyn OrmliteCodegen, attr: &TableMetadata) -> TokenStream { let box_future = crate::util::box_fut_ts(); let placeholder = db.placeholder_ts(); let db = db.database_ts(); - let query = format!( - "INSERT INTO \"{}\" ({{}}) VALUES ({{}}) RETURNING *", - attr.table_name - ); + let query = format!("INSERT INTO \"{}\" ({{}}) VALUES ({{}}) RETURNING *", attr.table_name); let bind_parameters = attr.database_columns().map(generate_conditional_bind); @@ -115,12 +114,14 @@ pub fn impl_InsertModel(db: &dyn OrmliteCodegen, meta: &ModelMetadata) -> TokenS let mut placeholder = db.placeholder(); let db = db.database_ts(); let insert_model = Ident::new(&insert_struct); - let fields = meta.database_columns() + let fields = meta + .database_columns() .filter(|&c| !c.has_database_default) .map(|c| c.column_name.clone()) .collect::>() .join(","); - let placeholders = meta.database_columns() + let placeholders = meta + .database_columns() .filter(|&c| !c.has_database_default) .map(|_| placeholder.next().unwrap()) .collect::>() @@ -130,17 +131,15 @@ pub fn impl_InsertModel(db: &dyn OrmliteCodegen, meta: &ModelMetadata) -> TokenS meta.inner.table_name, fields, placeholders, ); - let query_bindings = meta.database_columns() - .filter(|&c| !c.has_database_default) - .map(|c| { - if let Some(rust_default) = &c.rust_default { - let default: syn::Expr = syn::parse_str(&rust_default).expect("Failed to parse default_value"); - return quote! { - q = q.bind(#default); - } - } - insertion_binding(c) - }); + let query_bindings = meta.database_columns().filter(|&c| !c.has_database_default).map(|c| { + if let Some(rust_default) = &c.rust_default { + let default: syn::Expr = syn::parse_str(&rust_default).expect("Failed to parse default_value"); + return quote! { + q = q.bind(#default); + }; + } + insertion_binding(c) + }); let insert_join = meta.inner.many_to_one_joins().map(|c| insert_join(c)); @@ -178,7 +177,6 @@ pub fn impl_InsertModel(db: &dyn OrmliteCodegen, meta: &ModelMetadata) -> TokenS } } - /// Insert joined structs /// Assumed bindings: /// - `model`: model struct diff --git a/macro/src/codegen/insert_model.rs b/macro/src/codegen/insert_model.rs index 3a119943..59fa37b2 100644 --- a/macro/src/codegen/insert_model.rs +++ b/macro/src/codegen/insert_model.rs @@ -1,8 +1,8 @@ +use ormlite_attr::Ident; +use ormlite_attr::ModelMetadata; use proc_macro2::TokenStream; use quote::quote; use syn::DeriveInput; -use ormlite_attr::ModelMetadata; -use ormlite_attr::Ident; pub fn struct_InsertModel(ast: &DeriveInput, attr: &ModelMetadata) -> TokenStream { let Some(insert_model) = &attr.insert_struct else { @@ -10,19 +10,17 @@ pub fn struct_InsertModel(ast: &DeriveInput, attr: &ModelMetadata) -> TokenStrea }; let insert_model = Ident::new(insert_model); let vis = &ast.vis; - let struct_fields = attr.inner.columns.iter() - .filter(|c| !c.is_default()) - .map(|c| { - let id = &c.identifier; - let ty = &c.column_type; - quote! { - pub #id: #ty - } - }); + let struct_fields = attr.inner.columns.iter().filter(|c| !c.is_default()).map(|c| { + let id = &c.identifier; + let ty = &c.column_type; + quote! { + pub #id: #ty + } + }); quote! { #[derive(Debug)] #vis struct #insert_model { #(#struct_fields,)* } } -} \ No newline at end of file +} diff --git a/macro/src/codegen/into_arguments.rs b/macro/src/codegen/into_arguments.rs index d4bd0b08..e1b9d574 100644 --- a/macro/src/codegen/into_arguments.rs +++ b/macro/src/codegen/into_arguments.rs @@ -1,29 +1,28 @@ +use crate::codegen::common::OrmliteCodegen; +use ormlite_attr::TableMetadata; use proc_macro2::TokenStream; use quote::quote; -use ormlite_attr::TableMetadata; -use crate::codegen::common::OrmliteCodegen; /// Allows the model to be turned into arguments. This can be used for bulk insertion. pub fn impl_IntoArguments(db: &dyn OrmliteCodegen, attr: &TableMetadata) -> TokenStream { let mut placeholder = db.placeholder(); let db = db.database_ts(); let model = &attr.struct_name; - let params = attr.database_columns() - .map(|c| { - let field = &c.identifier; - let value = if c.is_json() || c.experimental_encode_as_json { - quote! { - ::ormlite::types::Json(self.#field) - } - } else { - quote! { - self.#field - } - }; + let params = attr.database_columns().map(|c| { + let field = &c.identifier; + let value = if c.is_json() || c.experimental_encode_as_json { quote! { - ::ormlite::Arguments::add(&mut args, #value); + ::ormlite::types::Json(self.#field) } - }); + } else { + quote! { + self.#field + } + }; + quote! { + ::ormlite::Arguments::add(&mut args, #value); + } + }); quote! { impl<'a> ::ormlite::IntoArguments<'a, #db> for #model { @@ -36,4 +35,4 @@ pub fn impl_IntoArguments(db: &dyn OrmliteCodegen, attr: &TableMetadata) -> Toke } } } -} \ No newline at end of file +} diff --git a/macro/src/codegen/join_description.rs b/macro/src/codegen/join_description.rs index 9418ebec..9433dc4b 100644 --- a/macro/src/codegen/join_description.rs +++ b/macro/src/codegen/join_description.rs @@ -1,8 +1,7 @@ - +use crate::MetadataCache; +use ormlite_attr::TableMetadata; use proc_macro2::TokenStream; use quote::quote; -use ormlite_attr::TableMetadata; -use crate::MetadataCache; pub fn static_join_descriptions(attr: &TableMetadata, metadata_cache: &MetadataCache) -> TokenStream { let model = &attr.struct_name; @@ -10,7 +9,9 @@ pub fn static_join_descriptions(attr: &TableMetadata, metadata_cache: &MetadataC let id = &c.identifier; let id_s = &c.identifier.to_string(); let struct_name = c.joined_struct_name().unwrap(); - let joined_table = metadata_cache.get(&struct_name).expect(&format!("Did not find metadata for joined struct: {}", struct_name)); + let joined_table = metadata_cache + .get(&struct_name) + .expect(&format!("Did not find metadata for joined struct: {}", struct_name)); let column_name = c.many_to_one_column_name.as_ref().unwrap(); let foreign_key = &joined_table.pkey.column_name; @@ -24,9 +25,12 @@ pub fn static_join_descriptions(attr: &TableMetadata, metadata_cache: &MetadataC panic!("Unknown join type"); }; let table_name = &joined_table.inner.table_name; - let columns = joined_table.inner.columns.iter().filter(|c| !c.is_join()).map(|c| { - c.identifier.to_string() - }); + let columns = joined_table + .inner + .columns + .iter() + .filter(|c| !c.is_join()) + .map(|c| c.identifier.to_string()); quote! { pub fn #id() -> ::ormlite::__private::JoinDescription { ::ormlite::__private::JoinDescription { @@ -52,4 +56,4 @@ pub fn static_join_descriptions(attr: &TableMetadata, metadata_cache: &MetadataC )* } } -} \ No newline at end of file +} diff --git a/macro/src/codegen/meta.rs b/macro/src/codegen/meta.rs index 6df6b15d..c621c619 100644 --- a/macro/src/codegen/meta.rs +++ b/macro/src/codegen/meta.rs @@ -1,7 +1,7 @@ +use ormlite_attr::ModelMetadata; +use ormlite_attr::TableMetadata; use proc_macro2::TokenStream; use quote::quote; -use ormlite_attr::TableMetadata; -use ormlite_attr::ModelMetadata; pub fn impl_TableMeta(meta: &TableMetadata, pkey: Option<&str>) -> TokenStream { let model = &meta.struct_name; @@ -11,8 +11,7 @@ pub fn impl_TableMeta(meta: &TableMetadata, pkey: Option<&str>) -> TokenStream { None => quote! { None }, }; - let field_names = meta.database_columns() - .map(|c| c.column_name.to_string()); + let field_names = meta.database_columns().map(|c| c.column_name.to_string()); quote! { impl ::ormlite::model::TableMeta for #model { diff --git a/macro/src/codegen/model.rs b/macro/src/codegen/model.rs index 889ee95d..66f6e24f 100644 --- a/macro/src/codegen/model.rs +++ b/macro/src/codegen/model.rs @@ -1,12 +1,11 @@ -use proc_macro2::TokenStream; -use quote::quote; -use ormlite_attr::ModelMetadata; use crate::codegen::common::OrmliteCodegen; use crate::codegen::insert::impl_Model__insert; use crate::codegen::select::impl_Model__select; use crate::codegen::update::impl_Model__update_all_fields; use crate::MetadataCache; - +use ormlite_attr::ModelMetadata; +use proc_macro2::TokenStream; +use quote::quote; pub fn impl_Model(db: &dyn OrmliteCodegen, attr: &ModelMetadata, metadata_cache: &MetadataCache) -> TokenStream { let model = &attr.inner.struct_name; @@ -86,7 +85,6 @@ pub fn impl_Model__delete(db: &dyn OrmliteCodegen, attr: &ModelMetadata) -> Toke } } - pub fn impl_Model__fetch_one(db: &dyn OrmliteCodegen, attr: &ModelMetadata) -> TokenStream { let mut placeholder = db.placeholder(); @@ -117,7 +115,6 @@ pub fn impl_Model__fetch_one(db: &dyn OrmliteCodegen, attr: &ModelMetadata) -> T } } - pub fn impl_Model__builder(attr: &ModelMetadata) -> TokenStream { let partial_model = &attr.builder_struct(); quote! { diff --git a/macro/src/codegen/model_builder.rs b/macro/src/codegen/model_builder.rs index c3a9bc47..e7fd7030 100644 --- a/macro/src/codegen/model_builder.rs +++ b/macro/src/codegen/model_builder.rs @@ -1,11 +1,11 @@ -use proc_macro2::TokenStream; -use quote::quote; -use syn::DeriveInput; -use ormlite_attr::TableMetadata; -use ormlite_attr::ModelMetadata; use crate::codegen::common::OrmliteCodegen; use crate::codegen::insert::impl_ModelBuilder__insert; use crate::codegen::update::impl_ModelBuilder__update; +use ormlite_attr::ModelMetadata; +use ormlite_attr::TableMetadata; +use proc_macro2::TokenStream; +use quote::quote; +use syn::DeriveInput; pub fn struct_ModelBuilder(ast: &DeriveInput, attr: &ModelMetadata) -> TokenStream { let model = &attr.inner.struct_name; @@ -46,45 +46,42 @@ pub fn struct_ModelBuilder(ast: &DeriveInput, attr: &ModelMetadata) -> TokenStre }); quote! { - #vis struct #model_builder<'a> { - #(#settable,)* - updating: Option<&'a #model>, - } + #vis struct #model_builder<'a> { + #(#settable,)* + updating: Option<&'a #model>, + } - impl<'a> std::default::Default for #model_builder<'a> { - fn default() -> Self { - Self { - #(#fields_none,)* - updating: None, - } + impl<'a> std::default::Default for #model_builder<'a> { + fn default() -> Self { + Self { + #(#fields_none,)* + updating: None, } } + } - impl<'a> #model_builder<'a> { - #(#methods)* + impl<'a> #model_builder<'a> { + #(#methods)* - } } + } } pub fn impl_ModelBuilder__build(attr: &TableMetadata) -> TokenStream { - let unpack = attr.database_columns() - .map(|c| { - let c = &c.identifier; - let msg = format!("Tried to build a model, but the field `{}` was not set.", c); - quote! { let #c = self.#c.expect(#msg); } - }); - - let fields = attr.database_columns() - .map(|c| &c.identifier); - - let skipped_fields = attr.columns.iter().filter(|&c| c.skip) - .map(|c| { - let id = &c.identifier; - quote! { - #id: Default::default() - } - }); + let unpack = attr.database_columns().map(|c| { + let c = &c.identifier; + let msg = format!("Tried to build a model, but the field `{}` was not set.", c); + quote! { let #c = self.#c.expect(#msg); } + }); + + let fields = attr.database_columns().map(|c| &c.identifier); + + let skipped_fields = attr.columns.iter().filter(|&c| c.skip).map(|c| { + let id = &c.identifier; + quote! { + #id: Default::default() + } + }); quote! { fn build(self) -> Self::Model { @@ -97,7 +94,6 @@ pub fn impl_ModelBuilder__build(attr: &TableMetadata) -> TokenStream { } } - pub fn impl_ModelBuilder(db: &dyn OrmliteCodegen, attr: &ModelMetadata) -> TokenStream { let partial_model = attr.builder_struct(); let model = &attr.struct_name(); @@ -131,4 +127,4 @@ pub fn impl_ModelBuilder(db: &dyn OrmliteCodegen, attr: &ModelMetadata) -> Token } } } -} \ No newline at end of file +} diff --git a/macro/src/codegen/mysql.rs b/macro/src/codegen/mysql.rs index 8b09e0c6..2d7e5453 100644 --- a/macro/src/codegen/mysql.rs +++ b/macro/src/codegen/mysql.rs @@ -24,4 +24,4 @@ impl OrmliteCodegen for MysqlBackend { fn row(&self) -> TokenStream { quote! { ::ormlite::mysql::MysqlRow } } -} \ No newline at end of file +} diff --git a/macro/src/codegen/postgres.rs b/macro/src/codegen/postgres.rs index 86c7379d..4868658d 100644 --- a/macro/src/codegen/postgres.rs +++ b/macro/src/codegen/postgres.rs @@ -1,8 +1,8 @@ use crate::codegen::common::{from_row_bounds, OrmliteCodegen}; +use crate::MetadataCache; use ormlite_core::query_builder::Placeholder; use proc_macro2::TokenStream; use quote::quote; -use crate::MetadataCache; pub struct PostgresBackend; @@ -28,53 +28,55 @@ impl OrmliteCodegen for PostgresBackend { } } - #[cfg(test)] mod test { use super::*; + use ormlite_attr::ttype::InnerType; use ormlite_attr::ColumnMetadata; use ormlite_attr::ModelMetadata; - use ormlite_attr::ttype::InnerType; #[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"), - ]); + 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"), - ]); + 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::>(); - assert_eq!(types_for_bound, vec![ - InnerType::new("u32"), - InnerType::new("String"), - InnerType::new("bool"), - ]); + 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 > ," + "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 > ," ); } } diff --git a/macro/src/codegen/select.rs b/macro/src/codegen/select.rs index b5e28e0a..4b584b4c 100644 --- a/macro/src/codegen/select.rs +++ b/macro/src/codegen/select.rs @@ -1,7 +1,7 @@ +use crate::codegen::common::OrmliteCodegen; +use ormlite_attr::TableMetadata; use proc_macro2::TokenStream; use quote::quote; -use ormlite_attr::TableMetadata; -use crate::codegen::common::OrmliteCodegen; pub fn impl_Model__select(db: &dyn OrmliteCodegen, attr: &TableMetadata) -> TokenStream { let table_name = &attr.table_name; @@ -12,4 +12,4 @@ pub fn impl_Model__select(db: &dyn OrmliteCodegen, attr: &TableMetadata) -> Toke .select(format!("\"{}\".*", #table_name)) } } -} \ No newline at end of file +} diff --git a/macro/src/codegen/update.rs b/macro/src/codegen/update.rs index c558cfdd..f030d12c 100644 --- a/macro/src/codegen/update.rs +++ b/macro/src/codegen/update.rs @@ -1,7 +1,7 @@ +use crate::codegen::common::{generate_conditional_bind, insertion_binding, OrmliteCodegen}; +use ormlite_attr::ModelMetadata; use proc_macro2::TokenStream; use quote::quote; -use ormlite_attr::ModelMetadata; -use crate::codegen::common::{generate_conditional_bind, insertion_binding, OrmliteCodegen}; pub fn impl_Model__update_all_fields(db: &dyn OrmliteCodegen, attr: &ModelMetadata) -> TokenStream { let box_future = crate::util::box_fut_ts(); @@ -53,7 +53,6 @@ pub fn impl_Model__update_all_fields(db: &dyn OrmliteCodegen, attr: &ModelMetada } } - pub fn impl_ModelBuilder__update(db: &dyn OrmliteCodegen, attr: &ModelMetadata) -> TokenStream { let box_future = crate::util::box_fut_ts(); let placeholder = db.placeholder_ts(); @@ -61,41 +60,41 @@ pub fn impl_ModelBuilder__update(db: &dyn OrmliteCodegen, attr: &ModelMetadata) let query = format!( "UPDATE \"{}\" SET {{}} WHERE {} = {{}} RETURNING *", - attr.table(), attr.pkey.column_name, + attr.table(), + attr.pkey.column_name, ); let bind_update = attr.database_columns().map(generate_conditional_bind); let id = &attr.pkey.identifier; quote! { - fn update<'e: 'a, E>(self, db: E) -> #box_future<'a, ::ormlite::Result> - where - E: 'e +::ormlite::Executor<'e, Database = #db>, - { - Box::pin(async move { - let mut placeholder = #placeholder; - let set_fields = self.modified_fields(); - let update_id = self.updating - .expect("Tried to call ModelBuilder::update(), but the ModelBuilder \ - has no reference to what model to update. You might have called \ - something like: `::build().update(&mut db)`. A partial update \ - looks something like \ - `.update_partial().update(&mut db)`.") - .#id - // NOTE: This clone is free for Copy types. .clone() fixes ormlite#13 - .clone(); - let query = format!( - #query, - set_fields.into_iter().map(|f| format!("{} = {}", f, placeholder.next().unwrap())).collect::>().join(", "), - placeholder.next().unwrap() - ); - let mut q =::ormlite::query_as::<#db, Self::Model>(&query); - #(#bind_update)* - q = q.bind(update_id); - q.fetch_one(db) - .await - .map_err(::ormlite::Error::from) - }) - } + fn update<'e: 'a, E>(self, db: E) -> #box_future<'a, ::ormlite::Result> + where + E: 'e +::ormlite::Executor<'e, Database = #db>, + { + Box::pin(async move { + let mut placeholder = #placeholder; + let set_fields = self.modified_fields(); + let update_id = self.updating + .expect("Tried to call ModelBuilder::update(), but the ModelBuilder \ + has no reference to what model to update. You might have called \ + something like: `::build().update(&mut db)`. A partial update \ + looks something like \ + `.update_partial().update(&mut db)`.") + .#id + // NOTE: This clone is free for Copy types. .clone() fixes ormlite#13 + .clone(); + let query = format!( + #query, + set_fields.into_iter().map(|f| format!("{} = {}", f, placeholder.next().unwrap())).collect::>().join(", "), + placeholder.next().unwrap() + ); + let mut q =::ormlite::query_as::<#db, Self::Model>(&query); + #(#bind_update)* + q = q.bind(update_id); + q.fetch_one(db) + .await + .map_err(::ormlite::Error::from) + }) } + } } - diff --git a/macro/src/lib.rs b/macro/src/lib.rs index d08da750..65568eef 100644 --- a/macro/src/lib.rs +++ b/macro/src/lib.rs @@ -10,17 +10,17 @@ use std::ops::Deref; use once_cell::sync::OnceCell; use quote::quote; -use syn::{Data, DeriveInput, parse_macro_input}; +use syn::{parse_macro_input, Data, DeriveInput}; use codegen::into_arguments::impl_IntoArguments; +use ormlite_attr::schema_from_filepaths; use ormlite_attr::DeriveInputExt; use ormlite_attr::ModelMetadata; -use ormlite_attr::schema_from_filepaths; use ormlite_attr::TableMetadata; use ormlite_core::config::get_var_model_folders; use crate::codegen::common::OrmliteCodegen; -use crate::codegen::from_row::{impl_from_row_using_aliases, impl_FromRow}; +use crate::codegen::from_row::{impl_FromRow, impl_from_row_using_aliases}; use crate::codegen::insert::impl_InsertModel; use crate::codegen::insert_model::struct_InsertModel; use crate::codegen::join_description::static_join_descriptions; @@ -28,8 +28,8 @@ use crate::codegen::meta::{impl_JoinMeta, impl_TableMeta}; use crate::codegen::model::{impl_HasModelBuilder, impl_Model}; use crate::codegen::model_builder::{impl_ModelBuilder, struct_ModelBuilder}; -mod util; mod codegen; +mod util; pub(crate) type MetadataCache = HashMap; @@ -71,7 +71,9 @@ fn get_databases(table_meta: &TableMetadata) -> Vec> { "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), + "sqlite" | "postgres" | "mysql" => { + panic!("Database {} is not enabled. Enable it with features = [\"{}\"]", db, db) + } _ => panic!("Unknown database: {}", db), } } @@ -105,7 +107,9 @@ fn get_databases(table_meta: &TableMetadata) -> Vec> { databases.push(Box::new(codegen::mysql::MysqlBackend {})); } if databases.is_empty() { - panic!(r#"No database is enabled. Enable one of these features for the ormlite crate: postgres, mysql, sqlite"#); + panic!( + r#"No database is enabled. Enable one of these features for the ormlite crate: postgres, mysql, sqlite"# + ); } databases } @@ -115,7 +119,9 @@ fn get_databases(table_meta: &TableMetadata) -> Vec> { #[proc_macro_derive(Model, attributes(ormlite))] pub fn expand_ormlite_model(input: TokenStream) -> TokenStream { let ast = parse_macro_input!(input as DeriveInput); - let Data::Struct(data) = &ast.data else { panic!("Only structs can derive Model"); }; + let Data::Struct(data) = &ast.data else { + panic!("Only structs can derive Model"); + }; let meta = ModelMetadata::from_derive(&ast).expect("Failed to parse table metadata"); @@ -174,7 +180,9 @@ pub fn expand_ormlite_model(input: TokenStream) -> TokenStream { #[proc_macro_derive(FromRow, attributes(ormlite))] pub fn expand_derive_fromrow(input: TokenStream) -> TokenStream { let ast = parse_macro_input!(input as DeriveInput); - let Data::Struct(data) = &ast.data else { panic!("Only structs can derive Model"); }; + let Data::Struct(data) = &ast.data else { + panic!("Only structs can derive Model"); + }; let meta = TableMetadata::from_derive(&ast).unwrap(); @@ -199,7 +207,9 @@ pub fn expand_derive_fromrow(input: TokenStream) -> TokenStream { #[proc_macro_derive(TableMeta, attributes(ormlite))] pub fn expand_derive_table_meta(input: TokenStream) -> TokenStream { let ast = parse_macro_input!(input as DeriveInput); - let Data::Struct(data) = &ast.data else { panic!("Only structs can derive Model"); }; + let Data::Struct(data) = &ast.data else { + panic!("Only structs can derive Model"); + }; let table_meta = TableMetadata::from_derive(&ast).expect("Failed to parse table metadata"); let databases = get_databases(&table_meta); @@ -212,7 +222,9 @@ pub fn expand_derive_table_meta(input: TokenStream) -> TokenStream { #[proc_macro_derive(IntoArguments, attributes(ormlite))] pub fn expand_derive_into_arguments(input: TokenStream) -> TokenStream { let ast = parse_macro_input!(input as DeriveInput); - let Data::Struct(data) = &ast.data else { panic!("Only structs can derive Model"); }; + let Data::Struct(data) = &ast.data else { + panic!("Only structs can derive Model"); + }; let meta = TableMetadata::from_derive(&ast).unwrap(); let databases = get_databases(&meta); @@ -233,4 +245,4 @@ pub fn expand_derive_into_arguments(input: TokenStream) -> TokenStream { #[proc_macro_derive(ManualType)] pub fn expand_derive_manual_type(input: TokenStream) -> TokenStream { TokenStream::new() -} \ No newline at end of file +} diff --git a/macro/src/util.rs b/macro/src/util.rs index 5f492fb9..24224de8 100644 --- a/macro/src/util.rs +++ b/macro/src/util.rs @@ -7,5 +7,3 @@ use syn::{DataStruct, DeriveInput, Field, Fields, FieldsNamed}; pub fn box_fut_ts() -> TokenStream { quote!(::ormlite::BoxFuture) } - - diff --git a/ormlite/src/lib.rs b/ormlite/src/lib.rs index 7bf92b10..0762e49c 100644 --- a/ormlite/src/lib.rs +++ b/ormlite/src/lib.rs @@ -1,29 +1,31 @@ #![cfg_attr(docsrs, feature(doc_cfg))] +pub use ::sqlx::{Column, ColumnIndex, Database, Decode, Row}; +pub use model::{FromRow, IntoArguments, Model, TableMeta}; pub use ormlite_core::BoxFuture; pub use ormlite_core::{Error, Result}; -pub use model::{Model, FromRow, TableMeta, IntoArguments}; -pub use ::sqlx::{Row, ColumnIndex, Decode, Column, Database}; -pub use ::sqlx::{query, query_as, query_as_with, Connection, Executor, Pool, Acquire, ConnectOptions, Encode, Arguments, query_with}; pub use ::sqlx::pool::PoolOptions; +pub use ::sqlx::{ + query, query_as, query_as_with, query_with, Acquire, Arguments, ConnectOptions, Connection, Encode, Executor, Pool, +}; pub mod model; pub mod query_builder { - pub use ormlite_core::query_builder::{SelectQueryBuilder, Placeholder, QueryBuilderArgs}; pub use ormlite_core::insert::OnConflict; + pub use ormlite_core::query_builder::{Placeholder, QueryBuilderArgs, SelectQueryBuilder}; } pub mod types { - pub use sqlx::types::*; pub use ormlite_macro::ManualType; + pub use sqlx::types::*; } pub mod decode { pub use sqlx::decode::*; } -pub use sqlx::{Error as SqlxError}; +pub use sqlx::Error as SqlxError; pub mod database { pub use sqlx::database::*; @@ -32,8 +34,8 @@ pub mod database { /// We need objects available for proc-macros that aren't meant to be available to end users. This module does that. #[doc(hidden)] pub mod __private { - pub use ormlite_core::join::{JoinDescription, SemanticJoinType}; pub use ormlite_core::insert::Insertion; + pub use ormlite_core::join::{JoinDescription, SemanticJoinType}; pub use sqlmo::Insert; pub use tokio_stream::StreamExt; } @@ -48,4 +50,4 @@ pub mod postgres { #[cfg_attr(docsrs, doc(cfg(feature = "sqlite")))] pub mod sqlite { pub use sqlx::sqlite::*; -} \ No newline at end of file +} diff --git a/ormlite/src/model.rs b/ormlite/src/model.rs index f449e7ee..bd78bc13 100644 --- a/ormlite/src/model.rs +++ b/ormlite/src/model.rs @@ -1,5 +1,5 @@ -pub use ormlite_core::model::*; pub use ormlite_core::join::{Join, JoinMeta, Loadable}; -pub use sqlx_core::from_row::FromRow; +pub use ormlite_core::model::*; +pub use ormlite_macro::{FromRow, IntoArguments, Model, TableMeta}; pub use sqlx::IntoArguments; -pub use ormlite_macro::{Model, FromRow, TableMeta, IntoArguments}; +pub use sqlx_core::from_row::FromRow; diff --git a/ormlite/tests/postgres.rs b/ormlite/tests/postgres.rs index 9c527f11..fe2a3e6b 100644 --- a/ormlite/tests/postgres.rs +++ b/ormlite/tests/postgres.rs @@ -7,4 +7,4 @@ use run::*; #[test] fn test_postgres_complex() { set_path_and_run("tests/postgres/complex.rs"); -} \ No newline at end of file +} diff --git a/ormlite/tests/run.rs b/ormlite/tests/run.rs index 48321abb..00221f3b 100644 --- a/ormlite/tests/run.rs +++ b/ormlite/tests/run.rs @@ -8,7 +8,6 @@ use trybuild::TestCases; const FOO: &str = env!("CARGO_MANIFEST_DIR"); - pub fn set_path_and_run(path: &str) { let t = TestCases::new(); let p = std::path::Path::new(&FOO).join(path); @@ -22,4 +21,4 @@ pub fn set_dir_and_run(dir: &str, subpath: &str) { let p = std::path::Path::new(&FOO).join(dir); std::env::set_var("MODEL_FOLDERS", p.display().to_string()); t.pass(p.join(subpath).display().to_string()); -} \ No newline at end of file +} diff --git a/ormlite/tests/simple.rs b/ormlite/tests/simple.rs index 480d21c8..42341aa4 100644 --- a/ormlite/tests/simple.rs +++ b/ormlite/tests/simple.rs @@ -10,17 +10,14 @@ pub struct Person { pub age: i16, } -pub static CREATE_TABLE_SQL: &str = - "CREATE TABLE person (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)"; +pub static CREATE_TABLE_SQL: &str = "CREATE TABLE person (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)"; #[tokio::test] async fn main() -> Result<(), Box> { let mut conn = ormlite::sqlite::SqliteConnection::connect(":memory:").await.unwrap(); env_logger::init(); - ormlite::query(CREATE_TABLE_SQL) - .execute(&mut conn) - .await?; + ormlite::query(CREATE_TABLE_SQL).execute(&mut conn).await?; // You can insert the model directly. let mut john = Person { @@ -33,11 +30,7 @@ async fn main() -> Result<(), Box> { println!("{:?}", john); println!("select"); - let people = Person::select() - .where_("age > ?") - .bind(50) - .fetch_all(&mut conn) - .await?; + let people = Person::select().where_("age > ?").bind(50).fetch_all(&mut conn).await?; println!("select query builder {:?}", people); let r = sqlx::query_as::<_, Person>("select * from person where age > ?") @@ -54,9 +47,7 @@ async fn main() -> Result<(), Box> { // Lastly, you can delete the object. john.delete(&mut conn).await?; // You can get a single user. - Person::fetch_one(1, &mut conn) - .await - .expect_err("Should not exist"); + Person::fetch_one(1, &mut conn).await.expect_err("Should not exist"); Person { id: 1, @@ -87,11 +78,7 @@ async fn main() -> Result<(), Box> { .await?; println!("built {:?}", kurt); // // You can create a query builder. - let people = Person::select() - .where_("age > ?") - .bind(50) - .fetch_all(&mut conn) - .await?; + let people = Person::select().where_("age > ?").bind(50).fetch_all(&mut conn).await?; println!("select builder {:?}", people); let people = Person::query("SELECT * FROM person WHERE age > ?")