diff --git a/sqlx-store/src/sqlite_store.rs b/sqlx-store/src/sqlite_store.rs index 5382e77..de21995 100644 --- a/sqlx-store/src/sqlite_store.rs +++ b/sqlx-store/src/sqlite_store.rs @@ -68,19 +68,30 @@ impl SqliteStore { Ok(()) } - async fn id_exists(&self, conn: &mut SqliteConnection, id: &Id) -> session_store::Result { + async fn try_create_with_conn( + &self, + conn: &mut SqliteConnection, + record: &Record, + ) -> session_store::Result { let query = format!( r#" - select exists(select 1 from {table_name} where id = ?) + insert or abort into {table_name} + (id, data, expiry_date) values (?, ?, ?) "#, table_name = self.table_name ); + let res = sqlx::query(&query) + .bind(record.id.to_string()) + .bind(rmp_serde::to_vec(record).map_err(SqlxStoreError::Encode)?) + .bind(record.expiry_date) + .execute(conn) + .await; - Ok(sqlx::query_scalar(&query) - .bind(id.to_string()) - .fetch_one(conn) - .await - .map_err(SqlxStoreError::Sqlx)?) + match res { + Ok(_) => Ok(true), + Err(sqlx::Error::Database(e)) if e.is_unique_violation() => Ok(false), + Err(e) => Err(SqlxStoreError::Sqlx(e).into()), + } } async fn save_with_conn( @@ -133,10 +144,9 @@ impl SessionStore for SqliteStore { async fn create(&self, record: &mut Record) -> session_store::Result<()> { let mut tx = self.pool.begin().await.map_err(SqlxStoreError::Sqlx)?; - while self.id_exists(&mut tx, &record.id).await? { + while !self.try_create_with_conn(&mut tx, record).await? { record.id = Id::default(); // Generate a new ID } - self.save_with_conn(&mut tx, record).await?; tx.commit().await.map_err(SqlxStoreError::Sqlx)?;