Skip to content

Commit 25c755b

Browse files
committed
refactor: make Config always compiled
simplifies usage while still making parsing optional for less generated code
1 parent 508983e commit 25c755b

File tree

12 files changed

+117
-65
lines changed

12 files changed

+117
-65
lines changed

Cargo.toml

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,14 @@ features = ["all-databases", "_unstable-all-types", "_unstable-doc"]
5454
rustdoc-args = ["--cfg", "docsrs"]
5555

5656
[features]
57-
default = ["any", "macros", "migrate", "json", "config-all"]
57+
default = ["any", "macros", "migrate", "json", "sqlx-toml"]
5858

5959
derive = ["sqlx-macros/derive"]
6060
macros = ["derive", "sqlx-macros/macros"]
6161
migrate = ["sqlx-core/migrate", "sqlx-macros?/migrate", "sqlx-mysql?/migrate", "sqlx-postgres?/migrate", "sqlx-sqlite?/migrate"]
6262

63-
# Enable parsing of `sqlx.toml` for configuring macros, migrations, or both.
64-
config-macros = ["sqlx-macros?/config-macros"]
65-
config-migrate = ["sqlx-macros?/config-migrate"]
66-
config-all = ["config-macros", "config-migrate"]
63+
# Enable parsing of `sqlx.toml` for configuring macros and migrations.
64+
sqlx-toml = ["sqlx-core/sqlx-toml", "sqlx-macros?/sqlx-toml"]
6765

6866
# intended mainly for CI and docs
6967
all-databases = ["mysql", "sqlite", "postgres", "any"]
@@ -79,7 +77,7 @@ _unstable-all-types = [
7977
"bit-vec",
8078
]
8179
# Render documentation that wouldn't otherwise be shown (e.g. `sqlx_core::config`).
82-
_unstable-doc = ["config-all", "sqlx-core/_unstable-doc"]
80+
_unstable-doc = []
8381

8482
# Base runtime features without TLS
8583
runtime-async-std = ["_rt-async-std", "sqlx-core/_rt-async-std", "sqlx-macros?/_rt-async-std"]

sqlx-cli/Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ filetime = "0.2"
5151
backoff = { version = "0.4.0", features = ["futures", "tokio"] }
5252

5353
[features]
54-
default = ["postgres", "sqlite", "mysql", "native-tls", "completions"]
54+
default = ["postgres", "sqlite", "mysql", "native-tls", "completions", "sqlx-toml"]
55+
5556
rustls = ["sqlx/runtime-tokio-rustls"]
5657
native-tls = ["sqlx/runtime-tokio-native-tls"]
5758

@@ -65,6 +66,8 @@ openssl-vendored = ["openssl/vendored"]
6566

6667
completions = ["dep:clap_complete"]
6768

69+
sqlx-toml = ["sqlx/sqlx-toml"]
70+
6871
[dev-dependencies]
6972
assert_cmd = "2.0.11"
7073
tempfile = "3.10.1"

sqlx-core/Cargo.toml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ features = ["offline"]
1212

1313
[features]
1414
default = []
15-
migrate = ["sha2", "crc", "config-migrate"]
15+
migrate = ["sha2", "crc"]
1616

1717
any = []
1818

@@ -30,11 +30,13 @@ _tls-none = []
3030
# support offline/decoupled building (enables serialization of `Describe`)
3131
offline = ["serde", "either/serde"]
3232

33-
config = ["serde", "toml/parse"]
34-
config-macros = ["config"]
35-
config-migrate = ["config"]
33+
# Enable parsing of `sqlx.toml`.
34+
# For simplicity, the `config` module is always enabled,
35+
# but disabling this disables the `serde` derives and the `toml` crate,
36+
# which is a good bit less code to compile if the feature isn't being used.
37+
sqlx-toml = ["serde", "toml/parse"]
3638

37-
_unstable-doc = ["config-macros", "config-migrate"]
39+
_unstable-doc = ["sqlx-toml"]
3840

3941
[dependencies]
4042
# Runtimes

sqlx-core/src/config/common.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/// Configuration shared by multiple components.
2-
#[derive(Debug, Default, serde::Deserialize)]
2+
#[derive(Debug, Default)]
3+
#[cfg_attr(feature = "sqlx-toml", derive(serde::Deserialize))]
34
pub struct Config {
45
/// Override the database URL environment variable.
56
///
@@ -36,3 +37,9 @@ pub struct Config {
3637
/// and the ones used in `bar` will use `BAR_DATABASE_URL`.
3738
pub database_url_var: Option<String>,
3839
}
40+
41+
impl Config {
42+
pub fn database_url_var(&self) -> &str {
43+
self.database_url_var.as_deref().unwrap_or("DATABASE_URL")
44+
}
45+
}

sqlx-core/src/config/macros.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use std::collections::BTreeMap;
22

33
/// Configuration for the `query!()` family of macros.
4-
#[derive(Debug, Default, serde::Deserialize)]
5-
#[serde(default)]
4+
#[derive(Debug, Default)]
5+
#[cfg_attr(feature = "sqlx-toml", derive(serde::Deserialize), serde(default))]
66
pub struct Config {
77
/// Specify the crate to use for mapping date/time types to Rust.
88
///
@@ -235,8 +235,12 @@ pub struct Config {
235235
}
236236

237237
/// The crate to use for mapping date/time types to Rust.
238-
#[derive(Debug, Default, PartialEq, Eq, serde::Deserialize)]
239-
#[serde(rename_all = "snake_case")]
238+
#[derive(Debug, Default, PartialEq, Eq)]
239+
#[cfg_attr(
240+
feature = "sqlx-toml",
241+
derive(serde::Deserialize),
242+
serde(rename_all = "snake_case")
243+
)]
240244
pub enum DateTimeCrate {
241245
/// Use whichever crate is enabled (`time` then `chrono`).
242246
#[default]

sqlx-core/src/config/migrate.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ use std::collections::BTreeSet;
1212
/// if the proper precautions are not taken.
1313
///
1414
/// Be sure you know what you are doing and that you read all relevant documentation _thoroughly_.
15-
#[derive(Debug, Default, serde::Deserialize)]
16-
#[serde(default)]
15+
#[derive(Debug, Default)]
16+
#[cfg_attr(feature = "sqlx-toml", derive(serde::Deserialize), serde(default))]
1717
pub struct Config {
1818
/// Override the name of the table used to track executed migrations.
1919
///
@@ -118,8 +118,12 @@ pub struct Config {
118118
}
119119

120120
/// The default type of migration that `sqlx migrate create` should create by default.
121-
#[derive(Debug, Default, PartialEq, Eq, serde::Deserialize)]
122-
#[serde(rename_all = "snake_case")]
121+
#[derive(Debug, Default, PartialEq, Eq)]
122+
#[cfg_attr(
123+
feature = "sqlx-toml",
124+
derive(serde::Deserialize),
125+
serde(rename_all = "snake_case")
126+
)]
123127
pub enum DefaultMigrationType {
124128
/// Create the same migration type as that of the latest existing migration,
125129
/// or `Simple` otherwise.
@@ -134,8 +138,12 @@ pub enum DefaultMigrationType {
134138
}
135139

136140
/// The default scheme that `sqlx migrate create` should use for version integers.
137-
#[derive(Debug, Default, PartialEq, Eq, serde::Deserialize)]
138-
#[serde(rename_all = "snake_case")]
141+
#[derive(Debug, Default, PartialEq, Eq)]
142+
#[cfg_attr(
143+
feature = "sqlx-toml",
144+
derive(serde::Deserialize),
145+
serde(rename_all = "snake_case")
146+
)]
139147
pub enum DefaultVersioning {
140148
/// Infer the versioning scheme from existing migrations:
141149
///

sqlx-core/src/config/mod.rs

Lines changed: 63 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//!
88
//! See the [reference][`_reference`] for the full `sqlx.toml` file.
99
10+
use std::error::Error;
1011
use std::fmt::Debug;
1112
use std::io;
1213
use std::path::{Path, PathBuf};
@@ -23,13 +24,11 @@ pub mod common;
2324
/// Configuration for the `query!()` family of macros.
2425
///
2526
/// See [`macros::Config`] for details.
26-
#[cfg(feature = "config-macros")]
2727
pub mod macros;
2828

2929
/// Configuration for migrations when executed using `sqlx::migrate!()` or through `sqlx-cli`.
3030
///
3131
/// See [`migrate::Config`] for details.
32-
#[cfg(feature = "config-migrate")]
3332
pub mod migrate;
3433

3534
/// Reference for `sqlx.toml` files
@@ -41,11 +40,12 @@ pub mod migrate;
4140
/// ```
4241
pub mod _reference {}
4342

44-
#[cfg(test)]
43+
#[cfg(all(test, feature = "sqlx-toml"))]
4544
mod tests;
4645

4746
/// The parsed structure of a `sqlx.toml` file.
48-
#[derive(Debug, Default, serde::Deserialize)]
47+
#[derive(Debug, Default)]
48+
#[cfg_attr(feature = "sqlx-toml", derive(serde::Deserialize))]
4949
pub struct Config {
5050
/// Configuration shared by multiple components.
5151
///
@@ -55,21 +55,11 @@ pub struct Config {
5555
/// Configuration for the `query!()` family of macros.
5656
///
5757
/// See [`macros::Config`] for details.
58-
#[cfg_attr(
59-
docsrs,
60-
doc(cfg(any(feature = "config-all", feature = "config-macros")))
61-
)]
62-
#[cfg(feature = "config-macros")]
6358
pub macros: macros::Config,
6459

6560
/// Configuration for migrations when executed using `sqlx::migrate!()` or through `sqlx-cli`.
6661
///
6762
/// See [`migrate::Config`] for details.
68-
#[cfg_attr(
69-
docsrs,
70-
doc(cfg(any(feature = "config-all", feature = "config-migrate")))
71-
)]
72-
#[cfg(feature = "config-migrate")]
7363
pub migrate: migrate::Config,
7464
}
7565

@@ -90,13 +80,17 @@ pub enum ConfigError {
9080
std::env::VarError,
9181
),
9282

83+
/// No configuration file was found. Not necessarily fatal.
84+
#[error("config file {path:?} not found")]
85+
NotFound {
86+
path: PathBuf,
87+
},
88+
9389
/// An I/O error occurred while attempting to read the config file at `path`.
9490
///
95-
/// This includes [`io::ErrorKind::NotFound`].
96-
///
97-
/// [`Self::not_found_path()`] will return the path if the file was not found.
91+
/// If the error is [`io::ErrorKind::NotFound`], [`Self::NotFound`] is returned instead.
9892
#[error("error reading config file {path:?}")]
99-
Read {
93+
Io {
10094
path: PathBuf,
10195
#[source]
10296
error: io::Error,
@@ -105,22 +99,41 @@ pub enum ConfigError {
10599
/// An error in the TOML was encountered while parsing the config file at `path`.
106100
///
107101
/// The error gives line numbers and context when printed with `Display`/`ToString`.
102+
///
103+
/// Only returned if the `sqlx-toml` feature is enabled.
108104
#[error("error parsing config file {path:?}")]
109105
Parse {
110106
path: PathBuf,
107+
/// Type-erased [`toml::de::Error`].
111108
#[source]
112-
error: toml::de::Error,
109+
error: Box<dyn Error + Send + Sync + 'static>,
110+
},
111+
112+
/// A `sqlx.toml` file was found or specified, but the `sqlx-toml` feature is not enabled.
113+
#[error("SQLx found config file at {path:?} but the `sqlx-toml` feature was not enabled")]
114+
ParseDisabled {
115+
path: PathBuf
113116
},
114117
}
115118

116119
impl ConfigError {
120+
/// Create a [`ConfigError`] from a [`std::io::Error`].
121+
///
122+
/// Maps to either `NotFound` or `Io`.
123+
pub fn from_io(path: PathBuf, error: io::Error) -> Self {
124+
if error.kind() == io::ErrorKind::NotFound {
125+
Self::NotFound { path }
126+
} else {
127+
Self::Io { path, error }
128+
}
129+
}
130+
117131
/// If this error means the file was not found, return the path that was attempted.
118132
pub fn not_found_path(&self) -> Option<&Path> {
119-
match self {
120-
ConfigError::Read { path, error } if error.kind() == io::ErrorKind::NotFound => {
121-
Some(path)
122-
}
123-
_ => None,
133+
if let Self::NotFound { path } = self {
134+
Some(path)
135+
} else {
136+
None
124137
}
125138
}
126139
}
@@ -140,14 +153,22 @@ impl Config {
140153
/// If the file exists but an unrecoverable error was encountered while parsing it.
141154
pub fn from_crate() -> &'static Self {
142155
Self::try_from_crate().unwrap_or_else(|e| {
143-
if let Some(path) = e.not_found_path() {
144-
// Non-fatal
145-
tracing::debug!("Not reading config, file {path:?} not found (error: {e})");
146-
CACHE.get_or_init(Config::default)
147-
} else {
156+
match e {
157+
ConfigError::NotFound { path } => {
158+
// Non-fatal
159+
tracing::debug!("Not reading config, file {path:?} not found");
160+
CACHE.get_or_init(Config::default)
161+
}
162+
// FATAL ERRORS BELOW:
148163
// In the case of migrations,
149164
// we can't proceed with defaults as they may be completely wrong.
150-
panic!("failed to read sqlx config: {e}")
165+
e @ ConfigError::ParseDisabled { .. } => {
166+
// Only returned if the file exists but the feature is not enabled.
167+
panic!("{e}")
168+
}
169+
e => {
170+
panic!("failed to read sqlx config: {e}")
171+
}
151172
}
152173
})
153174
}
@@ -188,19 +209,29 @@ impl Config {
188209
})
189210
}
190211

212+
#[cfg(feature = "sqlx-toml")]
191213
fn read_from(path: PathBuf) -> Result<Self, ConfigError> {
192214
// The `toml` crate doesn't provide an incremental reader.
193215
let toml_s = match std::fs::read_to_string(&path) {
194216
Ok(toml) => toml,
195217
Err(error) => {
196-
return Err(ConfigError::Read { path, error });
218+
return Err(ConfigError::from_io(path, error));
197219
}
198220
};
199221

200222
// TODO: parse and lint TOML structure before deserializing
201223
// Motivation: https://github.com/toml-rs/toml/issues/761
202224
tracing::debug!("read config TOML from {path:?}:\n{toml_s}");
203225

204-
toml::from_str(&toml_s).map_err(|error| ConfigError::Parse { path, error })
226+
toml::from_str(&toml_s).map_err(|error| ConfigError::Parse { path, error: Box::new(error) })
227+
}
228+
229+
#[cfg(not(feature = "sqlx-toml"))]
230+
fn read_from(path: PathBuf) -> Result<Self, ConfigError> {
231+
match path.try_exists() {
232+
Ok(true) => Err(ConfigError::ParseDisabled { path }),
233+
Ok(false) => Err(ConfigError::NotFound { path }),
234+
Err(e) => Err(ConfigError::from_io(path, e))
235+
}
205236
}
206237
}

sqlx-core/src/config/tests.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ fn assert_common_config(config: &config::common::Config) {
2020
assert_eq!(config.database_url_var.as_deref(), Some("FOO_DATABASE_URL"));
2121
}
2222

23-
#[cfg(feature = "config-macros")]
2423
fn assert_macros_config(config: &config::macros::Config) {
2524
use config::macros::*;
2625

@@ -74,7 +73,6 @@ fn assert_macros_config(config: &config::macros::Config) {
7473
);
7574
}
7675

77-
#[cfg(feature = "config-migrate")]
7876
fn assert_migrate_config(config: &config::migrate::Config) {
7977
use config::migrate::*;
8078

sqlx-core/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ pub mod any;
9191
#[cfg(feature = "migrate")]
9292
pub mod testing;
9393

94-
#[cfg(feature = "config")]
9594
pub mod config;
9695

9796
pub use error::{Error, Result};

sqlx-macros-core/Cargo.toml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,7 @@ derive = []
2323
macros = []
2424
migrate = ["sqlx-core/migrate"]
2525

26-
config = ["sqlx-core/config"]
27-
config-macros = ["config", "sqlx-core/config-macros"]
28-
config-migrate = ["config", "sqlx-core/config-migrate"]
26+
sqlx-toml = ["sqlx-core/sqlx-toml"]
2927

3028
# database
3129
mysql = ["sqlx-mysql"]

0 commit comments

Comments
 (0)