From 018a28e85f62e65ca36af5a90266cf277b00dd56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Raphael=20H=C3=B6ser?= Date: Mon, 10 Jun 2024 23:08:22 +0200 Subject: [PATCH 1/8] feat: support multiple types of DBs at once MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Raphael Höser --- sqlx-macros-core/src/query/mod.rs | 94 ++++++++++++++++++++++++------- 1 file changed, 75 insertions(+), 19 deletions(-) diff --git a/sqlx-macros-core/src/query/mod.rs b/sqlx-macros-core/src/query/mod.rs index cd5d14d85b..4f8ea2c524 100644 --- a/sqlx-macros-core/src/query/mod.rs +++ b/sqlx-macros-core/src/query/mod.rs @@ -41,38 +41,88 @@ impl QueryDriver { } } } + +pub struct QueryDataSourceUrl<'a> { + database_url: &'a str, + database_url_parsed: Url, +} + +impl<'a> From<&'a String> for QueryDataSourceUrl<'a> { + fn from(database_url: &'a String) -> Self { + let database_url_parsed = Url::parse(database_url).expect("invalid URL"); + + QueryDataSourceUrl { + database_url, + database_url_parsed, + } + } +} + pub enum QueryDataSource<'a> { Live { - database_url: &'a str, - database_url_parsed: Url, + database_urls: Vec>, }, Cached(DynQueryData), } impl<'a> QueryDataSource<'a> { - pub fn live(database_url: &'a str) -> crate::Result { + pub fn live(database_urls: Vec>) -> crate::Result { Ok(QueryDataSource::Live { - database_url, - database_url_parsed: database_url.parse()?, + database_urls, }) } pub fn matches_driver(&self, driver: &QueryDriver) -> bool { match self { Self::Live { - database_url_parsed, + database_urls, .. - } => driver.url_schemes.contains(&database_url_parsed.scheme()), + } => driver.url_schemes.iter().any(|scheme| { + database_urls.iter().any(|url| url.database_url_parsed.scheme() == *scheme) + }), Self::Cached(dyn_data) => dyn_data.db_name == driver.db_name, } } + + pub fn get_url_for_schemes(&self, schemes: &[&str]) -> Option<&QueryDataSourceUrl> { + match self { + Self::Live { + database_urls, + .. + } => { + for scheme in schemes { + if let Some(url) = database_urls.iter().find(|url| url.database_url_parsed.scheme() == *scheme) { + return Some(url); + } + } + None + } + Self::Cached(_) => { + None + } + } + } + + pub fn supported_schemes(&self) -> Vec<&str> { + match self { + Self::Live { + database_urls, + .. + } => { + let mut schemes = vec![]; + schemes.extend(database_urls.iter().map(|url| url.database_url_parsed.scheme())); + schemes + } + Self::Cached(..) => vec![], + } + } } struct Metadata { #[allow(unused)] manifest_dir: PathBuf, offline: bool, - database_url: Option, + database_urls: Vec, workspace_root: Arc>>, } @@ -139,12 +189,18 @@ static METADATA: Lazy = Lazy::new(|| { .map(|s| s.eq_ignore_ascii_case("true") || s == "1") .unwrap_or(false); - let database_url = env("DATABASE_URL").ok(); + let database_urls = vec![ + env("DATABASE_URL").ok(), + env("DATABASE_URL_POSTGRES").ok(), + env("DATABASE_URL_MARIADB").ok(), + env("DATABASE_URL_MYSQL").ok(), + env("DATABASE_URL_SQLITE").ok(), + ].into_iter().flatten().collect(); Metadata { manifest_dir, offline, - database_url, + database_urls, workspace_root: Arc::new(Mutex::new(None)), } }); @@ -156,9 +212,11 @@ pub fn expand_input<'a>( let data_source = match &*METADATA { Metadata { offline: false, - database_url: Some(db_url), + database_urls: db_urls, .. - } => QueryDataSource::live(db_url)?, + } => { + QueryDataSource::live(db_urls.iter().map(QueryDataSourceUrl::from).collect())? + }, Metadata { offline, .. } => { // Try load the cached query metadata file. @@ -196,12 +254,9 @@ pub fn expand_input<'a>( } match data_source { - QueryDataSource::Live { - database_url_parsed, - .. - } => Err(format!( + QueryDataSource::Live{..} => Err(format!( "no database driver found matching URL scheme {:?}; the corresponding Cargo feature may need to be enabled", - database_url_parsed.scheme() + data_source.supported_schemes() ).into()), QueryDataSource::Cached(data) => { Err(format!( @@ -221,8 +276,9 @@ where { let (query_data, offline): (QueryData, bool) = match data_source { QueryDataSource::Cached(dyn_data) => (QueryData::from_dyn_data(dyn_data)?, true), - QueryDataSource::Live { database_url, .. } => { - let describe = DB::describe_blocking(&input.sql, &database_url)?; + QueryDataSource::Live { .. } => { + let data_source_url = data_source.get_url_for_schemes(DB::URL_SCHEMES).unwrap(); + let describe = DB::describe_blocking(&input.sql, data_source_url.database_url)?; (QueryData::from_describe(&input.sql, describe), false) } }; From 726a6f9242bbf4956f0b2bb16e301da47f82468f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Raphael=20H=C3=B6ser?= Date: Mon, 10 Jun 2024 23:10:52 +0200 Subject: [PATCH 2/8] fix: make fallback env var the actual fallback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Raphael Höser --- sqlx-macros-core/src/query/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sqlx-macros-core/src/query/mod.rs b/sqlx-macros-core/src/query/mod.rs index 4f8ea2c524..af8bc40763 100644 --- a/sqlx-macros-core/src/query/mod.rs +++ b/sqlx-macros-core/src/query/mod.rs @@ -190,11 +190,13 @@ static METADATA: Lazy = Lazy::new(|| { .unwrap_or(false); let database_urls = vec![ - env("DATABASE_URL").ok(), env("DATABASE_URL_POSTGRES").ok(), env("DATABASE_URL_MARIADB").ok(), env("DATABASE_URL_MYSQL").ok(), env("DATABASE_URL_SQLITE").ok(), + + // Generic one last as a fallback + env("DATABASE_URL").ok(), ].into_iter().flatten().collect(); Metadata { From 21c947900221a76a9cedf432daaf1ca6e9811b8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Raphael=20H=C3=B6ser?= Date: Tue, 11 Jun 2024 22:59:09 +0200 Subject: [PATCH 3/8] Add working implementation with two drivers at once just for the query! macro. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Raphael Höser --- sqlx-macros-core/src/query/input.rs | 8 ++++++++ sqlx-macros-core/src/query/mod.rs | 23 ++++++++++++++++++++--- src/macros/mod.rs | 6 ++++++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/sqlx-macros-core/src/query/input.rs b/sqlx-macros-core/src/query/input.rs index 63e35ec77d..b3c9e6c687 100644 --- a/sqlx-macros-core/src/query/input.rs +++ b/sqlx-macros-core/src/query/input.rs @@ -19,6 +19,9 @@ pub struct QueryMacroInput { pub(super) checked: bool, pub(super) file_path: Option, + + // TODO: This should be some type and not a string + pub(super) driver: Option, } enum QuerySrc { @@ -38,6 +41,7 @@ impl Parse for QueryMacroInput { let mut args: Option> = None; let mut record_type = RecordType::Generated; let mut checked = true; + let mut driver = None; let mut expect_comma = false; @@ -82,6 +86,9 @@ impl Parse for QueryMacroInput { } else if key == "checked" { let lit_bool = input.parse::()?; checked = lit_bool.value; + } else if key == "driver" { + // TODO: This should be some actual type and not a string + driver = Some(input.parse::()?.value()); } else { let message = format!("unexpected input key: {key}"); return Err(syn::Error::new_spanned(key, message)); @@ -104,6 +111,7 @@ impl Parse for QueryMacroInput { arg_exprs, checked, file_path, + driver, }) } } diff --git a/sqlx-macros-core/src/query/mod.rs b/sqlx-macros-core/src/query/mod.rs index af8bc40763..d5a317a38f 100644 --- a/sqlx-macros-core/src/query/mod.rs +++ b/sqlx-macros-core/src/query/mod.rs @@ -209,7 +209,7 @@ static METADATA: Lazy = Lazy::new(|| { pub fn expand_input<'a>( input: QueryMacroInput, - drivers: impl IntoIterator, + drivers: impl IntoIterator + Iterator, ) -> crate::Result { let data_source = match &*METADATA { Metadata { @@ -249,9 +249,26 @@ pub fn expand_input<'a>( } }; + // If the driver was explicitly set, use it directly. + if let Some(input_driver) = input.driver.clone() { + for driver in drivers { + if driver.db_name == input_driver { + let result = (driver.expand)(input, data_source); + return result; + } + } + + return Err(format!( + "no database driver found matching {:?}; the corresponding Cargo feature may need to be enabled", + input_driver + ).into()); + } + + // If no driver was set, try to find a matching driver for the data source. for driver in drivers { - if data_source.matches_driver(&driver) { - return (driver.expand)(input, data_source); + if data_source.matches_driver(driver) { + let result = (driver.expand)(input, data_source); + return result; } } diff --git a/src/macros/mod.rs b/src/macros/mod.rs index 9c3c57111d..729e4eb5e6 100644 --- a/src/macros/mod.rs +++ b/src/macros/mod.rs @@ -316,6 +316,9 @@ macro_rules! query ( ($query:expr) => ({ $crate::sqlx_macros::expand_query!(source = $query) }); + ($driver:expr, $query:expr) => ({ + $crate::sqlx_macros::expand_query!(source = $query, driver = $driver) + }); // RFC: this semantically should be `$($args:expr),*` (with `$(,)?` to allow trailing comma) // but that doesn't work in 1.45 because `expr` fragments get wrapped in a way that changes // their hygiene, which is fixed in 1.46 so this is technically just a temp. workaround. @@ -326,6 +329,9 @@ macro_rules! query ( // not like it makes them magically understandable at-a-glance. ($query:expr, $($args:tt)*) => ({ $crate::sqlx_macros::expand_query!(source = $query, args = [$($args)*]) + }); + ($driver:expr, $query:expr, $($args:tt)*) => ({ + $crate::sqlx_macros::expand_query!(source = $query, args = [$($args)*], driver = $driver) }) ); From 3af2664fe52a9e4273805c5155355a1453d5b05d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Raphael=20H=C3=B6ser?= Date: Tue, 11 Jun 2024 23:04:53 +0200 Subject: [PATCH 4/8] Remove incorrect type bound that was added accidentally MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Raphael Höser --- sqlx-macros-core/src/query/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sqlx-macros-core/src/query/mod.rs b/sqlx-macros-core/src/query/mod.rs index d5a317a38f..0b540e5ba1 100644 --- a/sqlx-macros-core/src/query/mod.rs +++ b/sqlx-macros-core/src/query/mod.rs @@ -209,7 +209,7 @@ static METADATA: Lazy = Lazy::new(|| { pub fn expand_input<'a>( input: QueryMacroInput, - drivers: impl IntoIterator + Iterator, + drivers: impl IntoIterator, ) -> crate::Result { let data_source = match &*METADATA { Metadata { From 97b2fafcd074df92392b4de3b310fec7a3b546e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Raphael=20H=C3=B6ser?= Date: Wed, 12 Jun 2024 20:46:55 +0200 Subject: [PATCH 5/8] allow using any DATABASE_URL* env var for configuring DBs. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Raphael Höser --- sqlx-macros-core/src/query/mod.rs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/sqlx-macros-core/src/query/mod.rs b/sqlx-macros-core/src/query/mod.rs index 0b540e5ba1..6174db8d89 100644 --- a/sqlx-macros-core/src/query/mod.rs +++ b/sqlx-macros-core/src/query/mod.rs @@ -189,20 +189,10 @@ static METADATA: Lazy = Lazy::new(|| { .map(|s| s.eq_ignore_ascii_case("true") || s == "1") .unwrap_or(false); - let database_urls = vec![ - env("DATABASE_URL_POSTGRES").ok(), - env("DATABASE_URL_MARIADB").ok(), - env("DATABASE_URL_MYSQL").ok(), - env("DATABASE_URL_SQLITE").ok(), - - // Generic one last as a fallback - env("DATABASE_URL").ok(), - ].into_iter().flatten().collect(); - Metadata { manifest_dir, offline, - database_urls, + database_urls: env_db_urls(), workspace_root: Arc::new(Mutex::new(None)), } }); @@ -465,3 +455,7 @@ fn env(name: &str) -> Result { std::env::var(name) } } + +fn env_db_urls() -> Vec { + std::env::vars().filter(|(k, _)| k.starts_with("DATABASE_URL")).map(|(_, v)| v).collect() +} From d1d8c2571ba305e70dfa78d5eaa11bbe67fb3806 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Raphael=20H=C3=B6ser?= Date: Thu, 13 Jun 2024 21:25:52 +0200 Subject: [PATCH 6/8] Switch to a type based implementation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Raphael Höser --- sqlx-macros-core/src/lib.rs | 2 ++ sqlx-macros-core/src/query/input.rs | 6 ++-- sqlx-macros-core/src/query/mod.rs | 46 ++++++++++++++++++++++++----- src/macros/mod.rs | 4 +-- 4 files changed, 46 insertions(+), 12 deletions(-) diff --git a/sqlx-macros-core/src/lib.rs b/sqlx-macros-core/src/lib.rs index 0b2ab96270..82c9556d3f 100644 --- a/sqlx-macros-core/src/lib.rs +++ b/sqlx-macros-core/src/lib.rs @@ -18,6 +18,8 @@ any(sqlx_macros_unstable, procmacro2_semver_exempt), feature(track_path) )] +#![feature(const_type_name)] +#![feature(const_type_id)] #[cfg(feature = "macros")] use crate::query::QueryDriver; diff --git a/sqlx-macros-core/src/query/input.rs b/sqlx-macros-core/src/query/input.rs index b3c9e6c687..c664d8190a 100644 --- a/sqlx-macros-core/src/query/input.rs +++ b/sqlx-macros-core/src/query/input.rs @@ -7,6 +7,7 @@ use syn::{Expr, LitBool, LitStr, Token}; use syn::{ExprArray, Type}; /// Macro input shared by `query!()` and `query_file!()` +#[derive(Clone)] pub struct QueryMacroInput { pub(super) sql: String, @@ -21,7 +22,7 @@ pub struct QueryMacroInput { pub(super) file_path: Option, // TODO: This should be some type and not a string - pub(super) driver: Option, + pub(super) driver: Option, } enum QuerySrc { @@ -29,6 +30,7 @@ enum QuerySrc { File(String), } +#[derive(Clone)] pub enum RecordType { Given(Type), Scalar, @@ -88,7 +90,7 @@ impl Parse for QueryMacroInput { checked = lit_bool.value; } else if key == "driver" { // TODO: This should be some actual type and not a string - driver = Some(input.parse::()?.value()); + driver = Some(input.parse::()?); } else { let message = format!("unexpected input key: {key}"); return Err(syn::Error::new_spanned(key, message)); diff --git a/sqlx-macros-core/src/query/mod.rs b/sqlx-macros-core/src/query/mod.rs index 6174db8d89..01afdd3eb8 100644 --- a/sqlx-macros-core/src/query/mod.rs +++ b/sqlx-macros-core/src/query/mod.rs @@ -27,6 +27,7 @@ pub struct QueryDriver { db_name: &'static str, url_schemes: &'static [&'static str], expand: fn(QueryMacroInput, QueryDataSource) -> crate::Result, + db_type_name: &'static str, } impl QueryDriver { @@ -38,10 +39,12 @@ impl QueryDriver { db_name: DB::NAME, url_schemes: DB::URL_SCHEMES, expand: expand_with::, + db_type_name: std::any::type_name::(), } } } +#[derive(Clone)] pub struct QueryDataSourceUrl<'a> { database_url: &'a str, database_url_parsed: Url, @@ -58,6 +61,7 @@ impl<'a> From<&'a String> for QueryDataSourceUrl<'a> { } } +#[derive(Clone)] pub enum QueryDataSource<'a> { Live { database_urls: Vec>, @@ -239,19 +243,45 @@ pub fn expand_input<'a>( } }; + let mut working_drivers = vec![]; + // If the driver was explicitly set, use it directly. if let Some(input_driver) = input.driver.clone() { for driver in drivers { - if driver.db_name == input_driver { - let result = (driver.expand)(input, data_source); - return result; - } + if (driver.expand)(input.clone(), data_source.clone()).is_ok() { + working_drivers.push(driver); + } } - return Err(format!( - "no database driver found matching {:?}; the corresponding Cargo feature may need to be enabled", - input_driver - ).into()); + return match working_drivers.len() { + 0 => { + Err(format!( + "no database driver found matching for query; the corresponding Cargo feature may need to be enabled" + ).into()) + } + 1 => { + let driver = working_drivers.pop().unwrap(); + (driver.expand)(input, data_source) + } + _ => { + // todo!("Multiple drivers found matching the query, this is not yet supported."); + + let expansions = working_drivers.iter().map(|driver| { + let driver_name = driver.db_type_name; + let expanded = (driver.expand)(input.clone(), data_source.clone()).unwrap(); + quote! { + #driver_name => { + #expanded + } + } + }); + Ok(quote! { + match std::any::type_name::<#input_driver>() { + #(#expansions,)* + } + }) + } + } } // If no driver was set, try to find a matching driver for the data source. diff --git a/src/macros/mod.rs b/src/macros/mod.rs index 729e4eb5e6..4e4cf0668a 100644 --- a/src/macros/mod.rs +++ b/src/macros/mod.rs @@ -316,7 +316,7 @@ macro_rules! query ( ($query:expr) => ({ $crate::sqlx_macros::expand_query!(source = $query) }); - ($driver:expr, $query:expr) => ({ + ($driver:ty, $query:expr) => ({ $crate::sqlx_macros::expand_query!(source = $query, driver = $driver) }); // RFC: this semantically should be `$($args:expr),*` (with `$(,)?` to allow trailing comma) @@ -330,7 +330,7 @@ macro_rules! query ( ($query:expr, $($args:tt)*) => ({ $crate::sqlx_macros::expand_query!(source = $query, args = [$($args)*]) }); - ($driver:expr, $query:expr, $($args:tt)*) => ({ + ($driver:ty, $query:expr, $($args:tt)*) => ({ $crate::sqlx_macros::expand_query!(source = $query, args = [$($args)*], driver = $driver) }) ); From ebbe9796ff703b34074286c89cdd6067b06c9dcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Raphael=20H=C3=B6ser?= Date: Fri, 14 Jun 2024 16:45:18 +0200 Subject: [PATCH 7/8] Step further, but doesn't compile because the driver_type can't be referenced MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Raphael Höser --- sqlx-macros-core/src/query/mod.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/sqlx-macros-core/src/query/mod.rs b/sqlx-macros-core/src/query/mod.rs index 01afdd3eb8..73eb8f4198 100644 --- a/sqlx-macros-core/src/query/mod.rs +++ b/sqlx-macros-core/src/query/mod.rs @@ -268,16 +268,24 @@ pub fn expand_input<'a>( let expansions = working_drivers.iter().map(|driver| { let driver_name = driver.db_type_name; + let driver_type: Type = syn::parse_str(driver_name).unwrap(); let expanded = (driver.expand)(input.clone(), data_source.clone()).unwrap(); quote! { - #driver_name => { - #expanded + impl<'a> ProvideQuery<'a, #driver_type, _> for #driver_type { + fn provide_query() -> Query<'a, #driver_type, _> { + #expanded + } } } }); Ok(quote! { - match std::any::type_name::<#input_driver>() { - #(#expansions,)* + { + use sqlx::query::Query; + trait ProvideQuery<'a, DB, A> { + fn provide_query() -> Query<'a, DB, A>; + } + #(#expansions)* + ProvideQuery::<#input_driver, _>::provide_query() } }) } From a5d56859fd4a17d0bd8ccca61562670073ebb457 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Raphael=20H=C3=B6ser?= Date: Fri, 21 Jun 2024 16:35:42 +0200 Subject: [PATCH 8/8] Working version using types via associated const on DBs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Raphael Höser --- sqlx-core/src/any/database.rs | 2 ++ sqlx-core/src/database.rs | 4 ++++ sqlx-macros-core/src/lib.rs | 2 -- sqlx-macros-core/src/query/mod.rs | 14 ++++++-------- sqlx-mysql/src/database.rs | 2 ++ sqlx-postgres/src/database.rs | 2 ++ sqlx-sqlite/src/database.rs | 2 ++ 7 files changed, 18 insertions(+), 10 deletions(-) diff --git a/sqlx-core/src/any/database.rs b/sqlx-core/src/any/database.rs index 9c3f15bb1f..0b45116a13 100644 --- a/sqlx-core/src/any/database.rs +++ b/sqlx-core/src/any/database.rs @@ -33,6 +33,8 @@ impl Database for Any { const NAME: &'static str = "Any"; const URL_SCHEMES: &'static [&'static str] = &[]; + + const TYPE_IMPORT_PATH: &'static str = "sqlx::any::database::Any"; } // This _may_ be true, depending on the selected database diff --git a/sqlx-core/src/database.rs b/sqlx-core/src/database.rs index d17621c719..0f130546f0 100644 --- a/sqlx-core/src/database.rs +++ b/sqlx-core/src/database.rs @@ -108,6 +108,10 @@ pub trait Database: 'static + Sized + Send + Debug { /// The schemes for database URLs that should match this driver. const URL_SCHEMES: &'static [&'static str]; + + // This can be removed once https://github.com/rust-lang/rust/issues/63084 is resolved and type_name is available in const fns. + /// The path to the database-specific type system. + const TYPE_IMPORT_PATH: &'static str; } /// A [`Database`] that maintains a client-side cache of prepared statements. diff --git a/sqlx-macros-core/src/lib.rs b/sqlx-macros-core/src/lib.rs index 82c9556d3f..0b2ab96270 100644 --- a/sqlx-macros-core/src/lib.rs +++ b/sqlx-macros-core/src/lib.rs @@ -18,8 +18,6 @@ any(sqlx_macros_unstable, procmacro2_semver_exempt), feature(track_path) )] -#![feature(const_type_name)] -#![feature(const_type_id)] #[cfg(feature = "macros")] use crate::query::QueryDriver; diff --git a/sqlx-macros-core/src/query/mod.rs b/sqlx-macros-core/src/query/mod.rs index 73eb8f4198..0397ec03e0 100644 --- a/sqlx-macros-core/src/query/mod.rs +++ b/sqlx-macros-core/src/query/mod.rs @@ -39,7 +39,7 @@ impl QueryDriver { db_name: DB::NAME, url_schemes: DB::URL_SCHEMES, expand: expand_with::, - db_type_name: std::any::type_name::(), + db_type_name: DB::TYPE_IMPORT_PATH, } } } @@ -264,15 +264,13 @@ pub fn expand_input<'a>( (driver.expand)(input, data_source) } _ => { - // todo!("Multiple drivers found matching the query, this is not yet supported."); - let expansions = working_drivers.iter().map(|driver| { let driver_name = driver.db_type_name; let driver_type: Type = syn::parse_str(driver_name).unwrap(); let expanded = (driver.expand)(input.clone(), data_source.clone()).unwrap(); quote! { - impl<'a> ProvideQuery<'a, #driver_type, _> for #driver_type { - fn provide_query() -> Query<'a, #driver_type, _> { + impl ProvideQuery<#driver_type> for #driver_type { + fn provide_query<'a>() -> Query<'a, #driver_type, <#driver_type as sqlx::Database>::Arguments<'a>> { #expanded } } @@ -281,11 +279,11 @@ pub fn expand_input<'a>( Ok(quote! { { use sqlx::query::Query; - trait ProvideQuery<'a, DB, A> { - fn provide_query() -> Query<'a, DB, A>; + trait ProvideQuery { + fn provide_query<'a>() -> Query<'a, DB, DB::Arguments<'a>>; } #(#expansions)* - ProvideQuery::<#input_driver, _>::provide_query() + #input_driver::provide_query() } }) } diff --git a/sqlx-mysql/src/database.rs b/sqlx-mysql/src/database.rs index d03a567284..97a93f43a2 100644 --- a/sqlx-mysql/src/database.rs +++ b/sqlx-mysql/src/database.rs @@ -33,6 +33,8 @@ impl Database for MySql { const NAME: &'static str = "MySQL"; const URL_SCHEMES: &'static [&'static str] = &["mysql", "mariadb"]; + + const TYPE_IMPORT_PATH: &'static str = "sqlx::mysql::MySql"; } impl HasStatementCache for MySql {} diff --git a/sqlx-postgres/src/database.rs b/sqlx-postgres/src/database.rs index 876e295899..7956acbabf 100644 --- a/sqlx-postgres/src/database.rs +++ b/sqlx-postgres/src/database.rs @@ -35,6 +35,8 @@ impl Database for Postgres { const NAME: &'static str = "PostgreSQL"; const URL_SCHEMES: &'static [&'static str] = &["postgres", "postgresql"]; + + const TYPE_IMPORT_PATH: &'static str = "sqlx::postgres::Postgres"; } impl HasStatementCache for Postgres {} diff --git a/sqlx-sqlite/src/database.rs b/sqlx-sqlite/src/database.rs index c89c7b8322..7d70975eaa 100644 --- a/sqlx-sqlite/src/database.rs +++ b/sqlx-sqlite/src/database.rs @@ -34,6 +34,8 @@ impl Database for Sqlite { const NAME: &'static str = "SQLite"; const URL_SCHEMES: &'static [&'static str] = &["sqlite"]; + + const TYPE_IMPORT_PATH: &'static str = "sqlx::sqlite::Sqlite"; } impl HasStatementCache for Sqlite {}