From 546ec960a955959a649dda29180c3de52be0e181 Mon Sep 17 00:00:00 2001 From: joeydewaal <99046430+joeydewaal@users.noreply.github.com> Date: Tue, 28 Jan 2025 05:56:21 +0100 Subject: [PATCH] feat(Sqlite): add LockedSqliteHandle::last_error (#3707) --- ci.db | Bin 0 -> 36864 bytes sqlx-sqlite/src/connection/mod.rs | 6 +++++- sqlx-sqlite/src/error.rs | 12 ++++++++++-- tests/sqlite/sqlite.rs | 21 +++++++++++++++++++++ 4 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 ci.db diff --git a/ci.db b/ci.db new file mode 100644 index 0000000000000000000000000000000000000000..cc158a72804c405a8716f792f5ca51ec421c6ae0 GIT binary patch literal 36864 zcmeI*?{Cva7zgmXI6vw@Fd$8qCLvu`p~e#%tI)JpAkuJcBhqBJ?z+CROma|*U_NC8#&WYq);%-0a`BJb) zVf56K>=wC9C?$6pBZM^6qN^oORh22{1+}Fo@~34RTR+JzBHIzJnV;&9DGX2)a>e(ZWf=|2~2Z7}HZ zcE4^-544)OyiC7aO=FRVLP$3flktla+44d}Cw9z(TI+5ky!q)-j45lSPOyI+nMGDS z!Ls`BFi^uZYgHJ|{8`;cPuTjv=G~2ca@Mj|zQbZRU*|UOclb6-D_j0Z4epoas@YvW z?d;83rws1ui9%)CqBYYr>8qP_u5^E?Nc4Yj3a_u(fW;z^`Ebp7@A38aPS0VEy~E!r zRky5C)x2%~cMr3^Y3jXXDS1ChF7ivpkHq*zt&ku90SG_<0uX=z1Rwwb2tWV=5I7S8 zS4$OoT_@V67>~mnY&VR?qmOAt|4P@FlMe@(AFB_&lK)d~p$ z5P$##AOHafKmY;|fB*y_0D*HPP|+yWN}8tY$^1Vxej@6D1OW&@00Izz00bZa0SG_< z0uX?}*%DY$Q~vq`eNTA%O*WhOPkyH(Muqu*YP?nR|7WX%h!z46fB*y_009U<00Izz z00bZaf%g-b&;P$6#+&zRgQFk-0SG_<0uX=z1Rwwb2tWV=5cseKuF^8G^i2^>*gduK zgE$P5@Bgct{v$yE0uX=z1Rwwb2tWV=5P$##AaITalIwrX_?{TQ89%EH5(FRs0SG_< z0uX=z1Rwwb2tWV=AFjX^O(T}vS2y=p5054P0rX0#SVap}$^HK| { pub fn remove_rollback_hook(&mut self) { self.guard.remove_rollback_hook(); } + + pub fn last_error(&mut self) -> Option { + SqliteError::try_new(self.guard.handle.as_ptr()) + } } impl Drop for ConnectionState { diff --git a/sqlx-sqlite/src/error.rs b/sqlx-sqlite/src/error.rs index c00374fe60..0d34bc1026 100644 --- a/sqlx-sqlite/src/error.rs +++ b/sqlx-sqlite/src/error.rs @@ -23,9 +23,17 @@ pub struct SqliteError { impl SqliteError { pub(crate) fn new(handle: *mut sqlite3) -> Self { + Self::try_new(handle).expect("There should be an error") + } + + pub(crate) fn try_new(handle: *mut sqlite3) -> Option { // returns the extended result code even when extended result codes are disabled let code: c_int = unsafe { sqlite3_extended_errcode(handle) }; + if code == 0 { + return None; + } + // return English-language text that describes the error let message = unsafe { let msg = sqlite3_errmsg(handle); @@ -34,10 +42,10 @@ impl SqliteError { from_utf8_unchecked(CStr::from_ptr(msg).to_bytes()) }; - Self { + Some(Self { code, message: message.to_owned(), - } + }) } /// For errors during extension load, the error message is supplied via a separate pointer diff --git a/tests/sqlite/sqlite.rs b/tests/sqlite/sqlite.rs index d78e1151a9..16b4b2d9fa 100644 --- a/tests/sqlite/sqlite.rs +++ b/tests/sqlite/sqlite.rs @@ -1172,3 +1172,24 @@ async fn test_multiple_set_preupdate_hook_calls_drop_old_handler() -> anyhow::Re assert_eq!(1, Arc::strong_count(&ref_counted_object)); Ok(()) } + +#[sqlx_macros::test] +async fn test_get_last_error() -> anyhow::Result<()> { + let mut conn = new::().await?; + + let _ = sqlx::query("select 1").fetch_one(&mut conn).await?; + + { + let mut handle = conn.lock_handle().await?; + assert!(handle.last_error().is_none()); + } + + let _ = sqlx::query("invalid statement").fetch_one(&mut conn).await; + + { + let mut handle = conn.lock_handle().await?; + assert!(handle.last_error().is_some()); + } + + Ok(()) +}