Skip to content

Commit d9fd21c

Browse files
Don't cache sqlite connections for macros (#1930)
* fix(sqlx-macros): Don't cache sqlite connections for macros * Explicity close SQLite connection in query macro
1 parent 842e1ba commit d9fd21c

File tree

1 file changed

+52
-53
lines changed

1 file changed

+52
-53
lines changed

sqlx-macros/src/query/mod.rs

Lines changed: 52 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -187,64 +187,63 @@ pub fn expand_input(input: QueryMacroInput) -> crate::Result<TokenStream> {
187187
feature = "sqlite"
188188
))]
189189
fn expand_from_db(input: QueryMacroInput, db_url: &str) -> crate::Result<TokenStream> {
190-
use sqlx_core::any::{AnyConnection, AnyConnectionKind};
191-
192-
static CONNECTION_CACHE: Lazy<AsyncMutex<BTreeMap<String, AnyConnection>>> =
193-
Lazy::new(|| AsyncMutex::new(BTreeMap::new()));
190+
use sqlx_core::any::AnyConnection;
194191

195192
let maybe_expanded: crate::Result<TokenStream> = block_on(async {
196-
let mut cache = CONNECTION_CACHE.lock().await;
197-
198-
if !cache.contains_key(db_url) {
199-
let parsed_db_url = Url::parse(db_url)?;
200-
201-
let conn = match parsed_db_url.scheme() {
202-
#[cfg(feature = "sqlite")]
203-
"sqlite" => {
204-
use sqlx_core::connection::ConnectOptions;
205-
use sqlx_core::sqlite::{SqliteConnectOptions, SqliteJournalMode};
206-
use std::str::FromStr;
207-
208-
let sqlite_conn = SqliteConnectOptions::from_str(db_url)?
209-
// Connections in `CONNECTION_CACHE` won't get dropped so disable journaling
210-
// to avoid `.db-wal` and `.db-shm` files from lingering around
211-
.journal_mode(SqliteJournalMode::Off)
212-
.connect()
213-
.await?;
214-
AnyConnection::from(sqlite_conn)
215-
}
216-
_ => AnyConnection::connect(db_url).await?,
217-
};
218-
219-
let _ = cache.insert(db_url.to_owned(), conn);
220-
}
221-
222-
let conn_item = cache.get_mut(db_url).expect("Item was just inserted");
223-
match conn_item.private_get_mut() {
224-
#[cfg(feature = "postgres")]
225-
AnyConnectionKind::Postgres(conn) => {
226-
let data = QueryData::from_db(conn, &input.sql).await?;
227-
expand_with_data(input, data, false)
228-
}
229-
#[cfg(feature = "mssql")]
230-
AnyConnectionKind::Mssql(conn) => {
231-
let data = QueryData::from_db(conn, &input.sql).await?;
232-
expand_with_data(input, data, false)
233-
}
234-
#[cfg(feature = "mysql")]
235-
AnyConnectionKind::MySql(conn) => {
236-
let data = QueryData::from_db(conn, &input.sql).await?;
237-
expand_with_data(input, data, false)
238-
}
193+
let parsed_db_url = Url::parse(db_url)?;
194+
195+
match parsed_db_url.scheme() {
196+
// SQLite is not used in the connection cache due to issues with newly created
197+
// databases seemingly being locked for several seconds when journaling is off. This
198+
// isn't a huge issue since the intent of the connection cache was to make connections
199+
// to remote databases much faster. Relevant links:
200+
// - https://github.com/launchbadge/sqlx/pull/1782#issuecomment-1089226716
201+
// - https://github.com/launchbadge/sqlx/issues/1929
239202
#[cfg(feature = "sqlite")]
240-
AnyConnectionKind::Sqlite(conn) => {
241-
let data = QueryData::from_db(conn, &input.sql).await?;
203+
"sqlite" => {
204+
use sqlx_core::connection::ConnectOptions;
205+
use sqlx_core::sqlite::SqliteConnectOptions;
206+
use std::str::FromStr;
207+
208+
let mut conn = SqliteConnectOptions::from_str(db_url)?.connect().await?;
209+
let data = QueryData::from_db(&mut conn, &input.sql).await?;
210+
conn.close().await?;
242211
expand_with_data(input, data, false)
243212
}
244-
// Variants depend on feature flags
245-
#[allow(unreachable_patterns)]
246-
item => {
247-
return Err(format!("Missing expansion needed for: {:?}", item).into());
213+
_ => {
214+
static CONNECTION_CACHE: Lazy<AsyncMutex<BTreeMap<String, AnyConnection>>> =
215+
Lazy::new(|| AsyncMutex::new(BTreeMap::new()));
216+
217+
let mut cache = CONNECTION_CACHE.lock().await;
218+
219+
if !cache.contains_key(db_url) {
220+
let conn = AnyConnection::connect(db_url).await?;
221+
let _ = cache.insert(db_url.to_owned(), conn);
222+
}
223+
224+
let conn_item = cache.get_mut(db_url).expect("Item was just inserted");
225+
match conn_item.private_get_mut() {
226+
#[cfg(feature = "postgres")]
227+
sqlx_core::any::AnyConnectionKind::Postgres(conn) => {
228+
let data = QueryData::from_db(conn, &input.sql).await?;
229+
expand_with_data(input, data, false)
230+
}
231+
#[cfg(feature = "mssql")]
232+
sqlx_core::any::AnyConnectionKind::Mssql(conn) => {
233+
let data = QueryData::from_db(conn, &input.sql).await?;
234+
expand_with_data(input, data, false)
235+
}
236+
#[cfg(feature = "mysql")]
237+
sqlx_core::any::AnyConnectionKind::MySql(conn) => {
238+
let data = QueryData::from_db(conn, &input.sql).await?;
239+
expand_with_data(input, data, false)
240+
}
241+
// Variants depend on feature flags
242+
#[allow(unreachable_patterns)]
243+
item => {
244+
return Err(format!("Missing expansion needed for: {:?}", item).into());
245+
}
246+
}
248247
}
249248
}
250249
});

0 commit comments

Comments
 (0)