Add Connection::extension_init2

This commit is contained in:
gwenn 2023-07-09 15:53:03 +02:00
parent 92c536b622
commit 81585a75cb
6 changed files with 75 additions and 84 deletions

View File

@ -6263,49 +6263,23 @@ pub unsafe fn sqlite3_expanded_sql(
(fun)(arg1) (fun)(arg1)
} }
/// Loadable extension initialization error
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum InitError {
/// Invalid sqlite3_api_routines pointer
NullApiPointer,
/// Version mismatch between the extension and the SQLite3 library
VersionMismatch { compile_time: i32, runtime: i32 },
/// Invalid function pointer in one of sqlite3_api_routines fields
NullFunctionPointer,
}
impl ::std::fmt::Display for InitError {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
match *self {
InitError::NullApiPointer => {
write!(f, "Invalid sqlite3_api_routines pointer")
}
InitError::VersionMismatch { compile_time, runtime } => {
write!(f, "SQLite version mismatch: {runtime} < {compile_time}")
}
InitError::NullFunctionPointer => {
write!(f, "Some sqlite3_api_routines fields are null")
}
}
}
}
/// Like SQLITE_EXTENSION_INIT2 macro /// Like SQLITE_EXTENSION_INIT2 macro
pub unsafe fn rusqlite_extension_init2( pub unsafe fn rusqlite_extension_init2(
p_api: *mut sqlite3_api_routines, p_api: *mut sqlite3_api_routines,
) -> ::std::result::Result<(), InitError> { ) -> ::std::result::Result<(), crate::InitError> {
if p_api.is_null() { if p_api.is_null() {
return Err(InitError::NullApiPointer); return Err(crate::InitError::NullApiPointer);
} }
if let Some(fun) = (*p_api).libversion_number { if let Some(fun) = (*p_api).libversion_number {
let version = fun(); let version = fun();
if SQLITE_VERSION_NUMBER > version { if SQLITE_VERSION_NUMBER > version {
return Err(InitError::VersionMismatch { return Err(crate::InitError::VersionMismatch {
compile_time: SQLITE_VERSION_NUMBER, compile_time: SQLITE_VERSION_NUMBER,
runtime: version, runtime: version,
}); });
} }
} else { } else {
return Err(InitError::NullFunctionPointer); return Err(crate::InitError::NullFunctionPointer);
} }
__SQLITE3_AGGREGATE_CONTEXT __SQLITE3_AGGREGATE_CONTEXT
.store((*p_api).aggregate_context, ::atomic::Ordering::Release); .store((*p_api).aggregate_context, ::atomic::Ordering::Release);

View File

@ -773,38 +773,18 @@ mod loadable_extension {
} }
// (3) generate rust code similar to SQLITE_EXTENSION_INIT2 macro // (3) generate rust code similar to SQLITE_EXTENSION_INIT2 macro
let tokens = quote::quote! { let tokens = quote::quote! {
/// Loadable extension initialization error
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum InitError {
/// Invalid sqlite3_api_routines pointer
NullApiPointer,
/// Version mismatch between the extension and the SQLite3 library
VersionMismatch{compile_time: i32, runtime: i32},
/// Invalid function pointer in one of sqlite3_api_routines fields
NullFunctionPointer,
}
impl ::std::fmt::Display for InitError {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
match *self {
InitError::NullApiPointer => write!(f, "Invalid sqlite3_api_routines pointer"),
InitError::VersionMismatch{compile_time, runtime} => write!(f, "SQLite version mismatch: {runtime} < {compile_time}"),
InitError::NullFunctionPointer => write!(f, "Some sqlite3_api_routines fields are null"),
}
}
}
/// Like SQLITE_EXTENSION_INIT2 macro /// Like SQLITE_EXTENSION_INIT2 macro
pub unsafe fn rusqlite_extension_init2(#p_api: *mut #sqlite3_api_routines_ident) -> ::std::result::Result<(),InitError> { pub unsafe fn rusqlite_extension_init2(#p_api: *mut #sqlite3_api_routines_ident) -> ::std::result::Result<(),crate::InitError> {
if #p_api.is_null() { if #p_api.is_null() {
return Err(InitError::NullApiPointer); return Err(crate::InitError::NullApiPointer);
} }
if let Some(fun) = (*#p_api).libversion_number { if let Some(fun) = (*#p_api).libversion_number {
let version = fun(); let version = fun();
if SQLITE_VERSION_NUMBER > version { if SQLITE_VERSION_NUMBER > version {
return Err(InitError::VersionMismatch{compile_time: SQLITE_VERSION_NUMBER, runtime: version}); return Err(crate::InitError::VersionMismatch{compile_time: SQLITE_VERSION_NUMBER, runtime: version});
} }
} else { } else {
return Err(InitError::NullFunctionPointer); return Err(crate::InitError::NullFunctionPointer);
} }
#(#stores)* #(#stores)*
Ok(()) Ok(())

View File

@ -7459,49 +7459,23 @@ pub unsafe fn sqlite3_is_interrupted(arg1: *mut sqlite3) -> ::std::os::raw::c_in
(fun)(arg1) (fun)(arg1)
} }
/// Loadable extension initialization error
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum InitError {
/// Invalid sqlite3_api_routines pointer
NullApiPointer,
/// Version mismatch between the extension and the SQLite3 library
VersionMismatch { compile_time: i32, runtime: i32 },
/// Invalid function pointer in one of sqlite3_api_routines fields
NullFunctionPointer,
}
impl ::std::fmt::Display for InitError {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
match *self {
InitError::NullApiPointer => {
write!(f, "Invalid sqlite3_api_routines pointer")
}
InitError::VersionMismatch { compile_time, runtime } => {
write!(f, "SQLite version mismatch: {runtime} < {compile_time}")
}
InitError::NullFunctionPointer => {
write!(f, "Some sqlite3_api_routines fields are null")
}
}
}
}
/// Like SQLITE_EXTENSION_INIT2 macro /// Like SQLITE_EXTENSION_INIT2 macro
pub unsafe fn rusqlite_extension_init2( pub unsafe fn rusqlite_extension_init2(
p_api: *mut sqlite3_api_routines, p_api: *mut sqlite3_api_routines,
) -> ::std::result::Result<(), InitError> { ) -> ::std::result::Result<(), crate::InitError> {
if p_api.is_null() { if p_api.is_null() {
return Err(InitError::NullApiPointer); return Err(crate::InitError::NullApiPointer);
} }
if let Some(fun) = (*p_api).libversion_number { if let Some(fun) = (*p_api).libversion_number {
let version = fun(); let version = fun();
if SQLITE_VERSION_NUMBER > version { if SQLITE_VERSION_NUMBER > version {
return Err(InitError::VersionMismatch { return Err(crate::InitError::VersionMismatch {
compile_time: SQLITE_VERSION_NUMBER, compile_time: SQLITE_VERSION_NUMBER,
runtime: version, runtime: version,
}); });
} }
} else { } else {
return Err(InitError::NullFunctionPointer); return Err(crate::InitError::NullFunctionPointer);
} }
__SQLITE3_AGGREGATE_CONTEXT __SQLITE3_AGGREGATE_CONTEXT
.store((*p_api).aggregate_context, ::atomic::Ordering::Release); .store((*p_api).aggregate_context, ::atomic::Ordering::Release);

View File

@ -269,3 +269,37 @@ pub fn code_to_str(code: c_int) -> &'static str {
_ => "Unknown error code", _ => "Unknown error code",
} }
} }
/// Loadable extension initialization error
#[cfg(feature = "loadable_extension")]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum InitError {
/// Invalid sqlite3_api_routines pointer
NullApiPointer,
/// Version mismatch between the extension and the SQLite3 library
VersionMismatch { compile_time: i32, runtime: i32 },
/// Invalid function pointer in one of sqlite3_api_routines fields
NullFunctionPointer,
}
#[cfg(feature = "loadable_extension")]
impl ::std::fmt::Display for InitError {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
match *self {
InitError::NullApiPointer => {
write!(f, "Invalid sqlite3_api_routines pointer")
}
InitError::VersionMismatch {
compile_time,
runtime,
} => {
write!(f, "SQLite version mismatch: {runtime} < {compile_time}")
}
InitError::NullFunctionPointer => {
write!(f, "Some sqlite3_api_routines fields are null")
}
}
}
}
#[cfg(feature = "loadable_extension")]
impl error::Error for InitError {}

View File

@ -141,6 +141,10 @@ pub enum Error {
/// byte offset of the start of invalid token /// byte offset of the start of invalid token
offset: c_int, offset: c_int,
}, },
/// Loadable extension initialization error
#[cfg(feature = "loadable_extension")]
#[cfg_attr(docsrs, doc(cfg(feature = "loadable_extension")))]
InitError(ffi::InitError),
} }
impl PartialEq for Error { impl PartialEq for Error {
@ -200,6 +204,8 @@ impl PartialEq for Error {
offset: o2, offset: o2,
}, },
) => e1 == e2 && m1 == m2 && s1 == s2 && o1 == o2, ) => e1 == e2 && m1 == m2 && s1 == s2 && o1 == o2,
#[cfg(feature = "loadable_extension")]
(Error::InitError(e1), Error::InitError(e2)) => e1 == e2,
(..) => false, (..) => false,
} }
} }
@ -241,6 +247,14 @@ impl From<FromSqlError> for Error {
} }
} }
#[cfg(feature = "loadable_extension")]
impl From<ffi::InitError> for Error {
#[cold]
fn from(err: ffi::InitError) -> Error {
Error::InitError(err)
}
}
impl fmt::Display for Error { impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self { match *self {
@ -311,6 +325,8 @@ impl fmt::Display for Error {
ref sql, ref sql,
.. ..
} => write!(f, "{msg} in {sql} at offset {offset}"), } => write!(f, "{msg} in {sql} at offset {offset}"),
#[cfg(feature = "loadable_extension")]
Error::InitError(ref err) => err.fmt(f),
} }
} }
} }
@ -360,6 +376,8 @@ impl error::Error for Error {
Error::BlobSizeError => None, Error::BlobSizeError => None,
#[cfg(feature = "modern_sqlite")] #[cfg(feature = "modern_sqlite")]
Error::SqlInputError { ref error, .. } => Some(error), Error::SqlInputError { ref error, .. } => Some(error),
#[cfg(feature = "loadable_extension")]
Error::InitError(ref err) => Some(err),
} }
} }
} }

View File

@ -898,6 +898,17 @@ impl Connection {
}) })
} }
/// Like SQLITE_EXTENSION_INIT2 macro
#[cfg(feature = "loadable_extension")]
#[cfg_attr(docsrs, doc(cfg(feature = "loadable_extension")))]
pub unsafe fn extension_init2(
db: *mut ffi::sqlite3,
p_api: *mut ffi::sqlite3_api_routines,
) -> Result<Connection> {
ffi::rusqlite_extension_init2(p_api)?;
Connection::from_handle(db)
}
/// Create a `Connection` from a raw owned handle. /// Create a `Connection` from a raw owned handle.
/// ///
/// The returned connection will attempt to close the inner connection /// The returned connection will attempt to close the inner connection