/// The context received by an authorizer hook. /// /// See <https://sqlite.org/c3ref/set_authorizer.html> for more info. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pubstruct AuthContext<'c> { /// The action to be authorized. pub action: AuthAction<'c>,
/// The database name, if applicable. pub database_name: Option<&'c str>,
/// The inner-most trigger or view responsible for the access attempt. /// `None` if the access attempt was made by top-level SQL code. pub accessor: Option<&'c str>,
}
/// Actions and arguments found within a statement during /// preparation. /// /// See <https://sqlite.org/c3ref/c_alter_table.html> for more info. #[derive(Clone, Copy, Debug, Eq, PartialEq)] #[non_exhaustive] #[allow(missing_docs)] pubenum AuthAction<'c> { /// This variant is not normally produced by SQLite. You may encounter it // if you're using a different version than what's supported by this library.
Unknown { /// The unknown authorization action code.
code: i32, /// The third arg to the authorizer callback.
arg1: Option<&'c str>, /// The fourth arg to the authorizer callback.
arg2: Option<&'c str>,
},
CreateIndex {
index_name: &'c str,
table_name: &'c str,
},
CreateTable {
table_name: &'c str,
},
CreateTempIndex {
index_name: &'c str,
table_name: &'c str,
},
CreateTempTable {
table_name: &'c str,
},
CreateTempTrigger {
trigger_name: &'c str,
table_name: &'c str,
},
CreateTempView {
view_name: &'c str,
},
CreateTrigger {
trigger_name: &'c str,
table_name: &'c str,
},
CreateView {
view_name: &'c str,
},
Delete {
table_name: &'c str,
},
DropIndex {
index_name: &'c str,
table_name: &'c str,
},
DropTable {
table_name: &'c str,
},
DropTempIndex {
index_name: &'c str,
table_name: &'c str,
},
DropTempTable {
table_name: &'c str,
},
DropTempTrigger {
trigger_name: &'c str,
table_name: &'c str,
},
DropTempView {
view_name: &'c str,
},
DropTrigger {
trigger_name: &'c str,
table_name: &'c str,
},
DropView {
view_name: &'c str,
},
Insert {
table_name: &'c str,
},
Pragma {
pragma_name: &'c str, /// The pragma value, if present (e.g., `PRAGMA name = value;`).
pragma_value: Option<&'c str>,
},
Read {
table_name: &'c str,
column_name: &'c str,
},
Select,
Transaction {
operation: TransactionOperation,
},
Update {
table_name: &'c str,
column_name: &'c str,
},
Attach {
filename: &'c str,
},
Detach {
database_name: &'c str,
},
AlterTable {
database_name: &'c str,
table_name: &'c str,
},
Reindex {
index_name: &'c str,
},
Analyze {
table_name: &'c str,
},
CreateVtable {
table_name: &'c str,
module_name: &'c str,
},
DropVtable {
table_name: &'c str,
module_name: &'c str,
},
Function {
function_name: &'c str,
},
Savepoint {
operation: TransactionOperation,
savepoint_name: &'c str,
},
Recursive,
}
impl Connection { /// Register a callback function to be invoked whenever /// a transaction is committed. /// /// The callback returns `true` to rollback. #[inline] pubfn commit_hook<F>(&self, hook: Option<F>) where
F: FnMut() -> bool + Send + 'static,
{ self.db.borrow_mut().commit_hook(hook);
}
/// Register a callback function to be invoked whenever /// a transaction is committed. #[inline] pubfn rollback_hook<F>(&self, hook: Option<F>) where
F: FnMut() + Send + 'static,
{ self.db.borrow_mut().rollback_hook(hook);
}
/// Register a callback function to be invoked whenever /// a row is updated, inserted or deleted in a rowid table. /// /// The callback parameters are: /// /// - the type of database update (`SQLITE_INSERT`, `SQLITE_UPDATE` or /// `SQLITE_DELETE`), /// - the name of the database ("main", "temp", ...), /// - the name of the table that is updated, /// - the ROWID of the row that is updated. #[inline] pubfn update_hook<F>(&self, hook: Option<F>) where
F: FnMut(Action, &str, &str, i64) + Send + 'static,
{ self.db.borrow_mut().update_hook(hook);
}
/// Register a query progress callback. /// /// The parameter `num_ops` is the approximate number of virtual machine /// instructions that are evaluated between successive invocations of the /// `handler`. If `num_ops` is less than one then the progress handler /// is disabled. /// /// If the progress callback returns `true`, the operation is interrupted. pubfn progress_handler<F>(&self, num_ops: c_int, handler: Option<F>) where
F: FnMut() -> bool + Send + RefUnwindSafe + 'static,
{ self.db.borrow_mut().progress_handler(num_ops, handler);
}
/// Register an authorizer callback that's invoked /// as a statement is being prepared. #[inline] pubfn authorizer<'c, F>(&self, hook: Option<F>) where
F: for<'r> FnMut(AuthContext<'r>) -> Authorization + Send + RefUnwindSafe + 'static,
{ self.db.borrow_mut().authorizer(hook);
}
}
fn commit_hook<F>(&mutself, hook: Option<F>) where
F: FnMut() -> bool + Send + 'static,
{ unsafeextern"C"fn call_boxed_closure<F>(p_arg: *mut c_void) -> c_int where
F: FnMut() -> bool,
{ let r = catch_unwind(|| { let boxed_hook: *mut F = p_arg.cast::<F>();
(*boxed_hook)()
});
c_int::from(r.unwrap_or_default())
}
// unlike `sqlite3_create_function_v2`, we cannot specify a `xDestroy` with // `sqlite3_commit_hook`. so we keep the `xDestroy` function in // `InnerConnection.free_boxed_hook`. let free_commit_hook = if hook.is_some() {
Some(free_boxed_hook::<F> asunsafefn(*mut c_void))
} else {
None
};
let callback_fn = authorizer
.as_ref()
.map(|_| call_boxed_closure::<'c, F> as unsafe extern "C" fn(_, _, _, _, _, _) -> _); let boxed_authorizer = authorizer.map(Box::new);
matchunsafe {
ffi::sqlite3_set_authorizer( self.db(),
callback_fn,
boxed_authorizer
.as_ref()
.map_or_else(ptr::null_mut, |f| &**f as *const F as *mut _),
)
} {
ffi::SQLITE_OK => { self.authorizer = boxed_authorizer.map(|ba| ba as _);
}
err_code => { // The only error that `sqlite3_set_authorizer` returns is `SQLITE_MISUSE` // when compiled with `ENABLE_API_ARMOR` and the db pointer is invalid. // This library does not allow constructing a null db ptr, so if this branch // is hit, something very bad has happened. Panicking instead of returning // `Result` keeps this hook's API consistent with the others.
panic!("unexpectedly failed to set_authorizer: {}", unsafe { crate::error::error_from_handle(self.db(), err_code)
});
}
}
}
}
db.authorizer(None::<fn(AuthContext<'_>) -> Authorization>);
db.execute_batch("PRAGMA user_version=1").unwrap(); // Disallowed by first authorizer, but it's now removed.
Ok(())
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-06-17)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.