Skip to content

Commit 42def59

Browse files
authored
fix(macros): cache macro metadata based on CARGO_MANIFEST_DIR (#3815)
* fix(macros): cache macro metadata based on CARGO_MANIFEST_DIR * fix unrelated typo * bump dotenvy version * fix after review
1 parent e283bf9 commit 42def59

File tree

3 files changed

+32
-17
lines changed

3 files changed

+32
-17
lines changed

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ time = { version = "0.3.36", features = ["formatting", "parsing", "macros"] }
154154
uuid = "1.1.2"
155155

156156
# Common utility crates
157-
dotenvy = { version = "0.15.0", default-features = false }
157+
dotenvy = { version = "0.15.7", default-features = false }
158158

159159
# Runtimes
160160
[workspace.dependencies.async-std]

sqlx-macros-core/src/query/data.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ impl DynQueryData {
8686
let mut cache = OFFLINE_DATA_CACHE
8787
.lock()
8888
// Just reset the cache on error
89-
.unwrap_or_else(|posion_err| {
90-
let mut guard = posion_err.into_inner();
89+
.unwrap_or_else(|poison_err| {
90+
let mut guard = poison_err.into_inner();
9191
*guard = Default::default();
9292
guard
9393
});

sqlx-macros-core/src/query/mod.rs

+29-14
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::collections::HashMap;
12
use std::path::PathBuf;
23
use std::sync::{Arc, Mutex};
34
use std::{fs, io};
@@ -106,27 +107,28 @@ impl Metadata {
106107
}
107108
}
108109

110+
static METADATA: Lazy<Mutex<HashMap<String, Metadata>>> = Lazy::new(Default::default);
111+
109112
// If we are in a workspace, lookup `workspace_root` since `CARGO_MANIFEST_DIR` won't
110113
// reflect the workspace dir: https://github.com/rust-lang/cargo/issues/3946
111-
static METADATA: Lazy<Metadata> = Lazy::new(|| {
112-
let manifest_dir: PathBuf = env("CARGO_MANIFEST_DIR")
113-
.expect("`CARGO_MANIFEST_DIR` must be set")
114-
.into();
114+
fn init_metadata(manifest_dir: &String) -> Metadata {
115+
let manifest_dir: PathBuf = manifest_dir.into();
115116

116117
// If a .env file exists at CARGO_MANIFEST_DIR, load environment variables from this,
117118
// otherwise fallback to default dotenv behaviour.
118119
let env_path = manifest_dir.join(".env");
119120

120121
#[cfg_attr(not(procmacro2_semver_exempt), allow(unused_variables))]
121122
let env_path = if env_path.exists() {
122-
let res = dotenvy::from_path(&env_path);
123+
// Load the new environment variables and override the old ones if necessary.
124+
let res = dotenvy::from_path_override(&env_path);
123125
if let Err(e) = res {
124126
panic!("failed to load environment from {env_path:?}, {e}");
125127
}
126128

127129
Some(env_path)
128130
} else {
129-
dotenvy::dotenv().ok()
131+
dotenvy::dotenv_override().ok()
130132
};
131133

132134
// tell the compiler to watch the `.env` for changes, if applicable
@@ -147,32 +149,46 @@ static METADATA: Lazy<Metadata> = Lazy::new(|| {
147149
database_url,
148150
workspace_root: Arc::new(Mutex::new(None)),
149151
}
150-
});
152+
}
151153

152154
pub fn expand_input<'a>(
153155
input: QueryMacroInput,
154156
drivers: impl IntoIterator<Item = &'a QueryDriver>,
155157
) -> crate::Result<TokenStream> {
156-
let data_source = match &*METADATA {
158+
let manifest_dir = env("CARGO_MANIFEST_DIR").expect("`CARGO_MANIFEST_DIR` must be set");
159+
160+
let mut metadata_lock = METADATA
161+
.lock()
162+
// Just reset the metadata on error
163+
.unwrap_or_else(|poison_err| {
164+
let mut guard = poison_err.into_inner();
165+
*guard = Default::default();
166+
guard
167+
});
168+
169+
let metadata = metadata_lock
170+
.entry(manifest_dir)
171+
.or_insert_with_key(init_metadata);
172+
173+
let data_source = match &metadata {
157174
Metadata {
158175
offline: false,
159176
database_url: Some(db_url),
160177
..
161178
} => QueryDataSource::live(db_url)?,
162-
163179
Metadata { offline, .. } => {
164180
// Try load the cached query metadata file.
165181
let filename = format!("query-{}.json", hash_string(&input.sql));
166182

167183
// Check SQLX_OFFLINE_DIR, then local .sqlx, then workspace .sqlx.
168184
let dirs = [
169-
|| env("SQLX_OFFLINE_DIR").ok().map(PathBuf::from),
170-
|| Some(METADATA.manifest_dir.join(".sqlx")),
171-
|| Some(METADATA.workspace_root().join(".sqlx")),
185+
|_: &Metadata| env("SQLX_OFFLINE_DIR").ok().map(PathBuf::from),
186+
|meta: &Metadata| Some(meta.manifest_dir.join(".sqlx")),
187+
|meta: &Metadata| Some(meta.workspace_root().join(".sqlx")),
172188
];
173189
let Some(data_file_path) = dirs
174190
.iter()
175-
.filter_map(|path| path())
191+
.filter_map(|path| path(metadata))
176192
.map(|path| path.join(&filename))
177193
.find(|path| path.exists())
178194
else {
@@ -184,7 +200,6 @@ pub fn expand_input<'a>(
184200
}.into()
185201
);
186202
};
187-
188203
QueryDataSource::Cached(DynQueryData::from_data_file(&data_file_path, &input.sql)?)
189204
}
190205
};

0 commit comments

Comments
 (0)