Repository: launchbadge/sqlx
File: sqlx-macros/src/query/mod.rs (Rust)

Code before:

        #[cfg(not(feature = "offline"))]
        Metadata { offline: true, .. } => {
            Err("The cargo feature `offline` has to be enabled to use `SQLX_OFFLINE`".into())
        }

        #[cfg(not(feature = "offline"))]
        Metadata {
            offline: false,
            database_url: None,
            ..
        } => Err("`DATABASE_URL` must be set to use query macros".into()),
    }
}

#[derive(Debug)]
enum ConnectionCacheItem {
    #[cfg(feature = "postgres")]
    Postgres(sqlx_core::postgres::PgConnection),
    #[cfg(feature = "mssql")]
    MsSql(sqlx_core::mssql::MssqlConnection),
    #[cfg(feature = "mysql")]
    MySql(sqlx_core::mysql::MySqlConnection),
    #[cfg(feature = "sqlite")]
    Sqlite(sqlx_core::sqlite::SqliteConnection),
}

impl ConnectionCacheItem {
    async fn new(db_url: &Url) -> crate::Result<Self> {
        // FIXME: Introduce [sqlx::any::AnyConnection] and [sqlx::any::AnyDatabase] to support
        //        runtime determinism here
        match db_url.scheme() {
            #[cfg(feature = "postgres")]
            "postgres" | "postgresql" => {
                let conn = sqlx_core::postgres::PgConnection::connect(db_url.as_str()).await?;
                Ok(Self::Postgres(conn))
            }
            #[cfg(not(feature = "postgres"))]
            "postgres" | "postgresql" => Err(
                "database URL has the scheme of a PostgreSQL database but the `postgres` feature \
                is not enabled"
                    .into(),
            ),
            #[cfg(feature = "mssql")]
            "mssql" | "sqlserver" => {
                let conn = sqlx_core::mssql::MssqlConnection::connect(db_url.as_str()).await?;
                Ok(Self::MsSql(conn))
            }
            #[cfg(not(feature = "mssql"))]
            "mssql" | "sqlserver" => Err(
                "database URL has the scheme of a MSSQL database but the `mssql` feature is not \

Review comment (suggestion):
This is so annoyingly close to `AnyConnection` that I really hate seeing it defined twice.

The main issue with using `AnyConnection` here is that you'd want to destructure it to get into the database-specific implementations, but that's not exposed. I think I'd be okay exposing the minimum parts necessary (`AnyConnection::kind()`, `AnyConnectionKind`) as long as they're `#[doc(hidden)]`, though. I did consider suggesting an `unstable` feature here but `sqlx-macros` would have to enable that feature by default which makes it rather pointless anyway.

Code after:
            ..
        } => expand_from_db(input, &db_url),

        #[cfg(feature = "offline")]
        _ => {
            let data_file_path = METADATA.manifest_dir.join("sqlx-data.json");

            if data_file_path.exists() {
                expand_from_file(input, data_file_path)
            } else {
                let workspace_data_file_path = METADATA.workspace_root().join("sqlx-data.json");
                if workspace_data_file_path.exists() {
                    expand_from_file(input, workspace_data_file_path)
                } else {
                    Err(
                        "`DATABASE_URL` must be set, or `cargo sqlx prepare` must have been run \
                     and sqlx-data.json must exist, to use query macros"
                            .into(),
                    )
                }
            }
        }

        #[cfg(not(feature = "offline"))]
        Metadata { offline: true, .. } => {
            Err("The cargo feature `offline` has to be enabled to use `SQLX_OFFLINE`".into())
        }

        #[cfg(not(feature = "offline"))]
        Metadata {
            offline: false,
            database_url: None,
            ..
        } => Err("`DATABASE_URL` must be set to use query macros".into()),
    }
}

#[cfg(any(
    feature = "postgres",
    feature = "mysql",
    feature = "mssql",
    feature = "sqlite"
))]
fn expand_from_db(input: QueryMacroInput, db_url: &str) -> crate::Result<TokenStream> {
    use sqlx_core::any::{AnyConnection, AnyConnectionKind};

    static CONNECTION_CACHE: Lazy<AsyncMutex<BTreeMap<String, AnyConnection>>> =
        Lazy::new(|| AsyncMutex::new(BTreeMap::new()));

    let maybe_expanded: crate::Result<TokenStream> = block_on(async {
        let mut cache = CONNECTION_CACHE.lock().await;