mirror of
https://github.com/launchbadge/sqlx.git
synced 2025-09-29 22:12:04 +00:00
refactor: make Config
always compiled
simplifies usage while still making parsing optional for less generated code
This commit is contained in:
parent
9f34fc8dd2
commit
e775d2a3eb
10
Cargo.toml
10
Cargo.toml
@ -54,16 +54,14 @@ features = ["all-databases", "_unstable-all-types", "_unstable-doc"]
|
||||
rustdoc-args = ["--cfg", "docsrs"]
|
||||
|
||||
[features]
|
||||
default = ["any", "macros", "migrate", "json", "config-all"]
|
||||
default = ["any", "macros", "migrate", "json", "sqlx-toml"]
|
||||
|
||||
derive = ["sqlx-macros/derive"]
|
||||
macros = ["derive", "sqlx-macros/macros"]
|
||||
migrate = ["sqlx-core/migrate", "sqlx-macros?/migrate", "sqlx-mysql?/migrate", "sqlx-postgres?/migrate", "sqlx-sqlite?/migrate"]
|
||||
|
||||
# Enable parsing of `sqlx.toml` for configuring macros, migrations, or both.
|
||||
config-macros = ["sqlx-macros?/config-macros"]
|
||||
config-migrate = ["sqlx-macros?/config-migrate"]
|
||||
config-all = ["config-macros", "config-migrate"]
|
||||
# Enable parsing of `sqlx.toml` for configuring macros and migrations.
|
||||
sqlx-toml = ["sqlx-core/sqlx-toml", "sqlx-macros?/sqlx-toml"]
|
||||
|
||||
# intended mainly for CI and docs
|
||||
all-databases = ["mysql", "sqlite", "postgres", "any"]
|
||||
@ -79,7 +77,7 @@ _unstable-all-types = [
|
||||
"bit-vec",
|
||||
]
|
||||
# Render documentation that wouldn't otherwise be shown (e.g. `sqlx_core::config`).
|
||||
_unstable-doc = ["config-all", "sqlx-core/_unstable-doc"]
|
||||
_unstable-doc = []
|
||||
|
||||
# Base runtime features without TLS
|
||||
runtime-async-std = ["_rt-async-std", "sqlx-core/_rt-async-std", "sqlx-macros?/_rt-async-std"]
|
||||
|
@ -49,7 +49,8 @@ filetime = "0.2"
|
||||
backoff = { version = "0.4.0", features = ["futures", "tokio"] }
|
||||
|
||||
[features]
|
||||
default = ["postgres", "sqlite", "mysql", "native-tls", "completions"]
|
||||
default = ["postgres", "sqlite", "mysql", "native-tls", "completions", "sqlx-toml"]
|
||||
|
||||
rustls = ["sqlx/runtime-tokio-rustls"]
|
||||
native-tls = ["sqlx/runtime-tokio-native-tls"]
|
||||
|
||||
@ -64,6 +65,8 @@ openssl-vendored = ["openssl/vendored"]
|
||||
|
||||
completions = ["dep:clap_complete"]
|
||||
|
||||
sqlx-toml = ["sqlx/sqlx-toml"]
|
||||
|
||||
[dev-dependencies]
|
||||
assert_cmd = "2.0.11"
|
||||
tempfile = "3.10.1"
|
||||
|
@ -12,7 +12,7 @@ features = ["offline"]
|
||||
|
||||
[features]
|
||||
default = []
|
||||
migrate = ["sha2", "crc", "config-migrate"]
|
||||
migrate = ["sha2", "crc"]
|
||||
|
||||
any = []
|
||||
|
||||
@ -31,11 +31,13 @@ _tls-none = []
|
||||
# support offline/decoupled building (enables serialization of `Describe`)
|
||||
offline = ["serde", "either/serde"]
|
||||
|
||||
config = ["serde", "toml/parse"]
|
||||
config-macros = ["config"]
|
||||
config-migrate = ["config"]
|
||||
# Enable parsing of `sqlx.toml`.
|
||||
# For simplicity, the `config` module is always enabled,
|
||||
# but disabling this disables the `serde` derives and the `toml` crate,
|
||||
# which is a good bit less code to compile if the feature isn't being used.
|
||||
sqlx-toml = ["serde", "toml/parse"]
|
||||
|
||||
_unstable-doc = ["config-macros", "config-migrate"]
|
||||
_unstable-doc = ["sqlx-toml"]
|
||||
|
||||
[dependencies]
|
||||
# Runtimes
|
||||
|
@ -1,5 +1,6 @@
|
||||
/// Configuration shared by multiple components.
|
||||
#[derive(Debug, Default, serde::Deserialize)]
|
||||
#[derive(Debug, Default)]
|
||||
#[cfg_attr(feature = "sqlx-toml", derive(serde::Deserialize))]
|
||||
pub struct Config {
|
||||
/// Override the database URL environment variable.
|
||||
///
|
||||
@ -36,3 +37,9 @@ pub struct Config {
|
||||
/// and the ones used in `bar` will use `BAR_DATABASE_URL`.
|
||||
pub database_url_var: Option<String>,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn database_url_var(&self) -> &str {
|
||||
self.database_url_var.as_deref().unwrap_or("DATABASE_URL")
|
||||
}
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
/// Configuration for the `query!()` family of macros.
|
||||
#[derive(Debug, Default, serde::Deserialize)]
|
||||
#[serde(default)]
|
||||
#[derive(Debug, Default)]
|
||||
#[cfg_attr(feature = "sqlx-toml", derive(serde::Deserialize), serde(default))]
|
||||
pub struct Config {
|
||||
/// Specify the crate to use for mapping date/time types to Rust.
|
||||
///
|
||||
@ -235,8 +235,12 @@ pub struct Config {
|
||||
}
|
||||
|
||||
/// The crate to use for mapping date/time types to Rust.
|
||||
#[derive(Debug, Default, PartialEq, Eq, serde::Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[derive(Debug, Default, PartialEq, Eq)]
|
||||
#[cfg_attr(
|
||||
feature = "sqlx-toml",
|
||||
derive(serde::Deserialize),
|
||||
serde(rename_all = "snake_case")
|
||||
)]
|
||||
pub enum DateTimeCrate {
|
||||
/// Use whichever crate is enabled (`time` then `chrono`).
|
||||
#[default]
|
||||
|
@ -12,8 +12,8 @@ use std::collections::BTreeSet;
|
||||
/// if the proper precautions are not taken.
|
||||
///
|
||||
/// Be sure you know what you are doing and that you read all relevant documentation _thoroughly_.
|
||||
#[derive(Debug, Default, serde::Deserialize)]
|
||||
#[serde(default)]
|
||||
#[derive(Debug, Default)]
|
||||
#[cfg_attr(feature = "sqlx-toml", derive(serde::Deserialize), serde(default))]
|
||||
pub struct Config {
|
||||
/// Override the name of the table used to track executed migrations.
|
||||
///
|
||||
@ -118,8 +118,12 @@ pub struct Config {
|
||||
}
|
||||
|
||||
/// The default type of migration that `sqlx migrate create` should create by default.
|
||||
#[derive(Debug, Default, PartialEq, Eq, serde::Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[derive(Debug, Default, PartialEq, Eq)]
|
||||
#[cfg_attr(
|
||||
feature = "sqlx-toml",
|
||||
derive(serde::Deserialize),
|
||||
serde(rename_all = "snake_case")
|
||||
)]
|
||||
pub enum DefaultMigrationType {
|
||||
/// Create the same migration type as that of the latest existing migration,
|
||||
/// or `Simple` otherwise.
|
||||
@ -134,8 +138,12 @@ pub enum DefaultMigrationType {
|
||||
}
|
||||
|
||||
/// The default scheme that `sqlx migrate create` should use for version integers.
|
||||
#[derive(Debug, Default, PartialEq, Eq, serde::Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[derive(Debug, Default, PartialEq, Eq)]
|
||||
#[cfg_attr(
|
||||
feature = "sqlx-toml",
|
||||
derive(serde::Deserialize),
|
||||
serde(rename_all = "snake_case")
|
||||
)]
|
||||
pub enum DefaultVersioning {
|
||||
/// Infer the versioning scheme from existing migrations:
|
||||
///
|
||||
|
@ -7,6 +7,7 @@
|
||||
//!
|
||||
//! See the [reference][`_reference`] for the full `sqlx.toml` file.
|
||||
|
||||
use std::error::Error;
|
||||
use std::fmt::Debug;
|
||||
use std::io;
|
||||
use std::path::{Path, PathBuf};
|
||||
@ -23,13 +24,11 @@ pub mod common;
|
||||
/// Configuration for the `query!()` family of macros.
|
||||
///
|
||||
/// See [`macros::Config`] for details.
|
||||
#[cfg(feature = "config-macros")]
|
||||
pub mod macros;
|
||||
|
||||
/// Configuration for migrations when executed using `sqlx::migrate!()` or through `sqlx-cli`.
|
||||
///
|
||||
/// See [`migrate::Config`] for details.
|
||||
#[cfg(feature = "config-migrate")]
|
||||
pub mod migrate;
|
||||
|
||||
/// Reference for `sqlx.toml` files
|
||||
@ -41,11 +40,12 @@ pub mod migrate;
|
||||
/// ```
|
||||
pub mod _reference {}
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg(all(test, feature = "sqlx-toml"))]
|
||||
mod tests;
|
||||
|
||||
/// The parsed structure of a `sqlx.toml` file.
|
||||
#[derive(Debug, Default, serde::Deserialize)]
|
||||
#[derive(Debug, Default)]
|
||||
#[cfg_attr(feature = "sqlx-toml", derive(serde::Deserialize))]
|
||||
pub struct Config {
|
||||
/// Configuration shared by multiple components.
|
||||
///
|
||||
@ -55,21 +55,11 @@ pub struct Config {
|
||||
/// Configuration for the `query!()` family of macros.
|
||||
///
|
||||
/// See [`macros::Config`] for details.
|
||||
#[cfg_attr(
|
||||
docsrs,
|
||||
doc(cfg(any(feature = "config-all", feature = "config-macros")))
|
||||
)]
|
||||
#[cfg(feature = "config-macros")]
|
||||
pub macros: macros::Config,
|
||||
|
||||
/// Configuration for migrations when executed using `sqlx::migrate!()` or through `sqlx-cli`.
|
||||
///
|
||||
/// See [`migrate::Config`] for details.
|
||||
#[cfg_attr(
|
||||
docsrs,
|
||||
doc(cfg(any(feature = "config-all", feature = "config-migrate")))
|
||||
)]
|
||||
#[cfg(feature = "config-migrate")]
|
||||
pub migrate: migrate::Config,
|
||||
}
|
||||
|
||||
@ -90,13 +80,17 @@ pub enum ConfigError {
|
||||
std::env::VarError,
|
||||
),
|
||||
|
||||
/// No configuration file was found. Not necessarily fatal.
|
||||
#[error("config file {path:?} not found")]
|
||||
NotFound {
|
||||
path: PathBuf,
|
||||
},
|
||||
|
||||
/// An I/O error occurred while attempting to read the config file at `path`.
|
||||
///
|
||||
/// This includes [`io::ErrorKind::NotFound`].
|
||||
///
|
||||
/// [`Self::not_found_path()`] will return the path if the file was not found.
|
||||
/// If the error is [`io::ErrorKind::NotFound`], [`Self::NotFound`] is returned instead.
|
||||
#[error("error reading config file {path:?}")]
|
||||
Read {
|
||||
Io {
|
||||
path: PathBuf,
|
||||
#[source]
|
||||
error: io::Error,
|
||||
@ -105,22 +99,41 @@ pub enum ConfigError {
|
||||
/// An error in the TOML was encountered while parsing the config file at `path`.
|
||||
///
|
||||
/// The error gives line numbers and context when printed with `Display`/`ToString`.
|
||||
///
|
||||
/// Only returned if the `sqlx-toml` feature is enabled.
|
||||
#[error("error parsing config file {path:?}")]
|
||||
Parse {
|
||||
path: PathBuf,
|
||||
/// Type-erased [`toml::de::Error`].
|
||||
#[source]
|
||||
error: toml::de::Error,
|
||||
error: Box<dyn Error + Send + Sync + 'static>,
|
||||
},
|
||||
|
||||
/// A `sqlx.toml` file was found or specified, but the `sqlx-toml` feature is not enabled.
|
||||
#[error("SQLx found config file at {path:?} but the `sqlx-toml` feature was not enabled")]
|
||||
ParseDisabled {
|
||||
path: PathBuf
|
||||
},
|
||||
}
|
||||
|
||||
impl ConfigError {
|
||||
/// Create a [`ConfigError`] from a [`std::io::Error`].
|
||||
///
|
||||
/// Maps to either `NotFound` or `Io`.
|
||||
pub fn from_io(path: PathBuf, error: io::Error) -> Self {
|
||||
if error.kind() == io::ErrorKind::NotFound {
|
||||
Self::NotFound { path }
|
||||
} else {
|
||||
Self::Io { path, error }
|
||||
}
|
||||
}
|
||||
|
||||
/// If this error means the file was not found, return the path that was attempted.
|
||||
pub fn not_found_path(&self) -> Option<&Path> {
|
||||
match self {
|
||||
ConfigError::Read { path, error } if error.kind() == io::ErrorKind::NotFound => {
|
||||
Some(path)
|
||||
}
|
||||
_ => None,
|
||||
if let Self::NotFound { path } = self {
|
||||
Some(path)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -140,14 +153,22 @@ impl Config {
|
||||
/// If the file exists but an unrecoverable error was encountered while parsing it.
|
||||
pub fn from_crate() -> &'static Self {
|
||||
Self::try_from_crate().unwrap_or_else(|e| {
|
||||
if let Some(path) = e.not_found_path() {
|
||||
// Non-fatal
|
||||
tracing::debug!("Not reading config, file {path:?} not found (error: {e})");
|
||||
CACHE.get_or_init(Config::default)
|
||||
} else {
|
||||
match e {
|
||||
ConfigError::NotFound { path } => {
|
||||
// Non-fatal
|
||||
tracing::debug!("Not reading config, file {path:?} not found");
|
||||
CACHE.get_or_init(Config::default)
|
||||
}
|
||||
// FATAL ERRORS BELOW:
|
||||
// In the case of migrations,
|
||||
// we can't proceed with defaults as they may be completely wrong.
|
||||
panic!("failed to read sqlx config: {e}")
|
||||
e @ ConfigError::ParseDisabled { .. } => {
|
||||
// Only returned if the file exists but the feature is not enabled.
|
||||
panic!("{e}")
|
||||
}
|
||||
e => {
|
||||
panic!("failed to read sqlx config: {e}")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -188,12 +209,13 @@ impl Config {
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(feature = "sqlx-toml")]
|
||||
fn read_from(path: PathBuf) -> Result<Self, ConfigError> {
|
||||
// The `toml` crate doesn't provide an incremental reader.
|
||||
let toml_s = match std::fs::read_to_string(&path) {
|
||||
Ok(toml) => toml,
|
||||
Err(error) => {
|
||||
return Err(ConfigError::Read { path, error });
|
||||
return Err(ConfigError::from_io(path, error));
|
||||
}
|
||||
};
|
||||
|
||||
@ -201,6 +223,15 @@ impl Config {
|
||||
// Motivation: https://github.com/toml-rs/toml/issues/761
|
||||
tracing::debug!("read config TOML from {path:?}:\n{toml_s}");
|
||||
|
||||
toml::from_str(&toml_s).map_err(|error| ConfigError::Parse { path, error })
|
||||
toml::from_str(&toml_s).map_err(|error| ConfigError::Parse { path, error: Box::new(error) })
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "sqlx-toml"))]
|
||||
fn read_from(path: PathBuf) -> Result<Self, ConfigError> {
|
||||
match path.try_exists() {
|
||||
Ok(true) => Err(ConfigError::ParseDisabled { path }),
|
||||
Ok(false) => Err(ConfigError::NotFound { path }),
|
||||
Err(e) => Err(ConfigError::from_io(path, e))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,6 @@ fn assert_common_config(config: &config::common::Config) {
|
||||
assert_eq!(config.database_url_var.as_deref(), Some("FOO_DATABASE_URL"));
|
||||
}
|
||||
|
||||
#[cfg(feature = "config-macros")]
|
||||
fn assert_macros_config(config: &config::macros::Config) {
|
||||
use config::macros::*;
|
||||
|
||||
@ -74,7 +73,6 @@ fn assert_macros_config(config: &config::macros::Config) {
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "config-migrate")]
|
||||
fn assert_migrate_config(config: &config::migrate::Config) {
|
||||
use config::migrate::*;
|
||||
|
||||
|
@ -91,7 +91,6 @@ pub mod any;
|
||||
#[cfg(feature = "migrate")]
|
||||
pub mod testing;
|
||||
|
||||
#[cfg(feature = "config")]
|
||||
pub mod config;
|
||||
|
||||
pub use error::{Error, Result};
|
||||
|
@ -26,9 +26,7 @@ derive = []
|
||||
macros = []
|
||||
migrate = ["sqlx-core/migrate"]
|
||||
|
||||
config = ["sqlx-core/config"]
|
||||
config-macros = ["config", "sqlx-core/config-macros"]
|
||||
config-migrate = ["config", "sqlx-core/config-migrate"]
|
||||
sqlx-toml = ["sqlx-core/sqlx-toml"]
|
||||
|
||||
# database
|
||||
mysql = ["sqlx-mysql"]
|
||||
|
@ -16,6 +16,7 @@ use crate::query::data::{hash_string, DynQueryData, QueryData};
|
||||
use crate::query::input::RecordType;
|
||||
use either::Either;
|
||||
use url::Url;
|
||||
use sqlx_core::config::Config;
|
||||
|
||||
mod args;
|
||||
mod data;
|
||||
@ -138,8 +139,12 @@ static METADATA: Lazy<Metadata> = Lazy::new(|| {
|
||||
let offline = env("SQLX_OFFLINE")
|
||||
.map(|s| s.eq_ignore_ascii_case("true") || s == "1")
|
||||
.unwrap_or(false);
|
||||
|
||||
let database_url = env("DATABASE_URL").ok();
|
||||
|
||||
let var_name = Config::from_crate()
|
||||
.common
|
||||
.database_url_var();
|
||||
|
||||
let database_url = env(var_name).ok();
|
||||
|
||||
Metadata {
|
||||
manifest_dir,
|
||||
|
@ -27,8 +27,7 @@ derive = ["sqlx-macros-core/derive"]
|
||||
macros = ["sqlx-macros-core/macros"]
|
||||
migrate = ["sqlx-macros-core/migrate"]
|
||||
|
||||
config-macros = ["sqlx-macros-core/config-macros"]
|
||||
config-migrate = ["sqlx-macros-core/config-migrate"]
|
||||
sqlx-toml = ["sqlx-macros-core/sqlx-toml"]
|
||||
|
||||
# database
|
||||
mysql = ["sqlx-macros-core/mysql"]
|
||||
|
Loading…
x
Reference in New Issue
Block a user