sqlx_macros_core/
lib.rs

1//! Support crate for SQLx's proc macros.
2//!
3//! ### Note: Semver Exempt API
4//! The API of this crate is not meant for general use and does *not* follow Semantic Versioning.
5//! The only crate that follows Semantic Versioning in the project is the `sqlx` crate itself.
6//! If you are building a custom SQLx driver, you should pin an exact version of this and
7//! `sqlx-core` to avoid breakages:
8//!
9//! ```toml
10//! sqlx-core = "=0.6.2"
11//! sqlx-macros-core = "=0.6.2"
12//! ```
13//!
14//! And then make releases in lockstep with `sqlx-core`. We recommend all driver crates, in-tree
15//! or otherwise, use the same version numbers as `sqlx-core` to avoid confusion.
16
17#![cfg_attr(
18    any(sqlx_macros_unstable, procmacro2_semver_exempt),
19    feature(track_path)
20)]
21
22use cfg_if::cfg_if;
23use std::path::PathBuf;
24
25#[cfg(feature = "macros")]
26use crate::query::QueryDriver;
27
28pub type Error = Box<dyn std::error::Error>;
29
30pub type Result<T, E = Error> = std::result::Result<T, E>;
31
32mod common;
33pub mod database;
34
35#[cfg(feature = "derive")]
36pub mod derives;
37#[cfg(feature = "macros")]
38pub mod query;
39
40#[cfg(feature = "macros")]
41// The compiler gives misleading help messages about `#[cfg(test)]` when this is just named `test`.
42pub mod test_attr;
43
44#[cfg(feature = "migrate")]
45pub mod migrate;
46
47#[cfg(feature = "macros")]
48pub const FOSS_DRIVERS: &[QueryDriver] = &[
49    #[cfg(feature = "mysql")]
50    QueryDriver::new::<sqlx_mysql::MySql>(),
51    #[cfg(feature = "postgres")]
52    QueryDriver::new::<sqlx_postgres::Postgres>(),
53    #[cfg(feature = "_sqlite")]
54    QueryDriver::new::<sqlx_sqlite::Sqlite>(),
55];
56
57pub fn block_on<F>(f: F) -> F::Output
58where
59    F: std::future::Future,
60{
61    cfg_if! {
62        if #[cfg(feature = "_rt-async-global-executor")] {
63            sqlx_core::rt::test_block_on(f)
64        } else if #[cfg(feature = "_rt-async-std")] {
65            async_std::task::block_on(f)
66        } else if #[cfg(feature = "_rt-smol")] {
67            sqlx_core::rt::test_block_on(f)
68        } else if #[cfg(feature = "_rt-tokio")] {
69            use std::sync::LazyLock;
70
71            use tokio::runtime::{self, Runtime};
72
73            // We need a single, persistent Tokio runtime since we're caching connections,
74            // otherwise we'll get "IO driver has terminated" errors.
75            static TOKIO_RT: LazyLock<Runtime> = LazyLock::new(|| {
76                runtime::Builder::new_current_thread()
77                    .enable_all()
78                    .build()
79                    .expect("failed to start Tokio runtime")
80            });
81
82            TOKIO_RT.block_on(f)
83        } else {
84            sqlx_core::rt::missing_rt(f)
85        }
86    }
87}
88
89pub fn env(var: &str) -> Result<String> {
90    env_opt(var)?
91        .ok_or_else(|| format!("env var {var:?} must be set to use the query macros").into())
92}
93
94#[allow(clippy::disallowed_methods)]
95pub fn env_opt(var: &str) -> Result<Option<String>> {
96    use std::env::VarError;
97
98    #[cfg(any(sqlx_macros_unstable, procmacro2_semver_exempt))]
99    let res: Result<String, VarError> = proc_macro::tracked_env::var(var);
100
101    #[cfg(not(any(sqlx_macros_unstable, procmacro2_semver_exempt)))]
102    let res: Result<String, VarError> = std::env::var(var);
103
104    match res {
105        Ok(val) => Ok(Some(val)),
106        Err(VarError::NotPresent) => Ok(None),
107        Err(VarError::NotUnicode(_)) => Err(format!("env var {var:?} is not valid UTF-8").into()),
108    }
109}
110
111pub fn manifest_dir() -> Result<PathBuf> {
112    Ok(env("CARGO_MANIFEST_DIR")?.into())
113}