mirror of
https://github.com/isar/rusqlite.git
synced 2025-03-29 08:44:27 +08:00
Use C string literal for database name
No alloc for "main" and "temp". No alloc possible when the attached database name is known at compile time / a C string literal can be usd. No alloc when the database name is given by SQLite (`sqlite3_wal_hook`).
This commit is contained in:
parent
0af8bfc603
commit
3d85c79891
@ -207,8 +207,8 @@ impl Backup<'_, '_> {
|
|||||||
to: &'b mut Connection,
|
to: &'b mut Connection,
|
||||||
to_name: DatabaseName<'_>,
|
to_name: DatabaseName<'_>,
|
||||||
) -> Result<Backup<'a, 'b>> {
|
) -> Result<Backup<'a, 'b>> {
|
||||||
let to_name = to_name.as_cstring()?;
|
let to_name = to_name.as_cstr()?;
|
||||||
let from_name = from_name.as_cstring()?;
|
let from_name = from_name.as_cstr()?;
|
||||||
|
|
||||||
let to_db = to.db.borrow_mut().db;
|
let to_db = to.db.borrow_mut().db;
|
||||||
|
|
||||||
|
@ -346,7 +346,7 @@ impl InnerConnection {
|
|||||||
fn remove_preupdate_hook(&mut self) {}
|
fn remove_preupdate_hook(&mut self) {}
|
||||||
|
|
||||||
pub fn db_readonly(&self, db_name: super::DatabaseName<'_>) -> Result<bool> {
|
pub fn db_readonly(&self, db_name: super::DatabaseName<'_>) -> Result<bool> {
|
||||||
let name = db_name.as_cstring()?;
|
let name = db_name.as_cstr()?;
|
||||||
let r = unsafe { ffi::sqlite3_db_readonly(self.db, name.as_ptr()) };
|
let r = unsafe { ffi::sqlite3_db_readonly(self.db, name.as_ptr()) };
|
||||||
match r {
|
match r {
|
||||||
0 => Ok(false),
|
0 => Ok(false),
|
||||||
@ -368,7 +368,7 @@ impl InnerConnection {
|
|||||||
db_name: Option<super::DatabaseName<'_>>,
|
db_name: Option<super::DatabaseName<'_>>,
|
||||||
) -> Result<super::transaction::TransactionState> {
|
) -> Result<super::transaction::TransactionState> {
|
||||||
let r = if let Some(ref name) = db_name {
|
let r = if let Some(ref name) = db_name {
|
||||||
let name = name.as_cstring()?;
|
let name = name.as_cstr()?;
|
||||||
unsafe { ffi::sqlite3_txn_state(self.db, name.as_ptr()) }
|
unsafe { ffi::sqlite3_txn_state(self.db, name.as_ptr()) }
|
||||||
} else {
|
} else {
|
||||||
unsafe { ffi::sqlite3_txn_state(self.db, ptr::null()) }
|
unsafe { ffi::sqlite3_txn_state(self.db, ptr::null()) }
|
||||||
|
30
src/lib.rs
30
src/lib.rs
@ -347,12 +347,12 @@ fn path_to_cstring(p: &Path) -> Result<CString> {
|
|||||||
pub enum DatabaseName<'a> {
|
pub enum DatabaseName<'a> {
|
||||||
/// The main database.
|
/// The main database.
|
||||||
Main,
|
Main,
|
||||||
|
|
||||||
/// The temporary database (e.g., any "CREATE TEMPORARY TABLE" tables).
|
/// The temporary database (e.g., any "CREATE TEMPORARY TABLE" tables).
|
||||||
Temp,
|
Temp,
|
||||||
|
|
||||||
/// A database that has been attached via "ATTACH DATABASE ...".
|
/// A database that has been attached via "ATTACH DATABASE ...".
|
||||||
Attached(&'a str),
|
Attached(&'a str),
|
||||||
|
/// Optim
|
||||||
|
C(&'a CStr),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shorthand for [`DatabaseName::Main`].
|
/// Shorthand for [`DatabaseName::Main`].
|
||||||
@ -361,16 +361,24 @@ pub const MAIN_DB: DatabaseName<'static> = DatabaseName::Main;
|
|||||||
/// Shorthand for [`DatabaseName::Temp`].
|
/// Shorthand for [`DatabaseName::Temp`].
|
||||||
pub const TEMP_DB: DatabaseName<'static> = DatabaseName::Temp;
|
pub const TEMP_DB: DatabaseName<'static> = DatabaseName::Temp;
|
||||||
|
|
||||||
// Currently DatabaseName is only used by the backup and blob mods, so hide
|
|
||||||
// this (private) impl to avoid dead code warnings.
|
|
||||||
impl DatabaseName<'_> {
|
impl DatabaseName<'_> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn as_cstring(&self) -> Result<SmallCString> {
|
fn as_cstr(&self) -> Result<std::borrow::Cow<'_, CStr>> {
|
||||||
use self::DatabaseName::{Attached, Main, Temp};
|
Ok(match *self {
|
||||||
match *self {
|
DatabaseName::Main => std::borrow::Cow::Borrowed(c"main"),
|
||||||
Main => str_to_cstring("main"), // TODO C-string literals
|
DatabaseName::Temp => std::borrow::Cow::Borrowed(c"temp"),
|
||||||
Temp => str_to_cstring("temp"),
|
DatabaseName::Attached(s) => std::borrow::Cow::Owned(CString::new(s)?),
|
||||||
Attached(s) => str_to_cstring(s),
|
DatabaseName::C(s) => std::borrow::Cow::Borrowed(s),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
#[cfg(feature = "hooks")]
|
||||||
|
pub(crate) fn from_cstr(cs: &std::ffi::CStr) -> DatabaseName<'_> {
|
||||||
|
if cs == c"main" {
|
||||||
|
DatabaseName::Main
|
||||||
|
} else if cs == c"temp" {
|
||||||
|
DatabaseName::Temp
|
||||||
|
} else {
|
||||||
|
DatabaseName::C(cs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(feature = "hooks")]
|
#[cfg(feature = "hooks")]
|
||||||
@ -647,7 +655,7 @@ impl Connection {
|
|||||||
pub fn path(&self) -> Option<&str> {
|
pub fn path(&self) -> Option<&str> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let db = self.handle();
|
let db = self.handle();
|
||||||
let db_name = DatabaseName::Main.as_cstring().unwrap();
|
let db_name = DatabaseName::Main.as_cstr().unwrap();
|
||||||
let db_filename = ffi::sqlite3_db_filename(db, db_name.as_ptr());
|
let db_filename = ffi::sqlite3_db_filename(db, db_name.as_ptr());
|
||||||
if db_filename.is_null() {
|
if db_filename.is_null() {
|
||||||
None
|
None
|
||||||
|
@ -47,6 +47,7 @@ impl Sql {
|
|||||||
DatabaseName::Main => self.buf.push_str("main"),
|
DatabaseName::Main => self.buf.push_str("main"),
|
||||||
DatabaseName::Temp => self.buf.push_str("temp"),
|
DatabaseName::Temp => self.buf.push_str("temp"),
|
||||||
DatabaseName::Attached(s) => self.push_identifier(s),
|
DatabaseName::Attached(s) => self.push_identifier(s),
|
||||||
|
DatabaseName::C(s) => self.push_identifier(s.to_str().expect("invalid database name")),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ impl Deref for Data<'_> {
|
|||||||
impl Connection {
|
impl Connection {
|
||||||
/// Serialize a database.
|
/// Serialize a database.
|
||||||
pub fn serialize(&self, schema: DatabaseName) -> Result<Data> {
|
pub fn serialize(&self, schema: DatabaseName) -> Result<Data> {
|
||||||
let schema = schema.as_cstring()?;
|
let schema = schema.as_cstr()?;
|
||||||
let mut sz = 0;
|
let mut sz = 0;
|
||||||
let mut ptr: *mut u8 = unsafe {
|
let mut ptr: *mut u8 = unsafe {
|
||||||
ffi::sqlite3_serialize(
|
ffi::sqlite3_serialize(
|
||||||
@ -102,7 +102,7 @@ impl Connection {
|
|||||||
data: OwnedData,
|
data: OwnedData,
|
||||||
read_only: bool,
|
read_only: bool,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let schema = schema.as_cstring()?;
|
let schema = schema.as_cstr()?;
|
||||||
let (data, sz) = data.into_raw();
|
let (data, sz) = data.into_raw();
|
||||||
let sz = sz.try_into().unwrap();
|
let sz = sz.try_into().unwrap();
|
||||||
let flags = if read_only {
|
let flags = if read_only {
|
||||||
|
@ -42,7 +42,7 @@ impl Session<'_> {
|
|||||||
db: &'conn Connection,
|
db: &'conn Connection,
|
||||||
name: DatabaseName<'_>,
|
name: DatabaseName<'_>,
|
||||||
) -> Result<Session<'conn>> {
|
) -> Result<Session<'conn>> {
|
||||||
let name = name.as_cstring()?;
|
let name = name.as_cstr()?;
|
||||||
|
|
||||||
let db = db.db.borrow_mut().db;
|
let db = db.db.borrow_mut().db;
|
||||||
|
|
||||||
@ -154,7 +154,7 @@ impl Session<'_> {
|
|||||||
|
|
||||||
/// Load the difference between tables.
|
/// Load the difference between tables.
|
||||||
pub fn diff(&mut self, from: DatabaseName<'_>, table: &str) -> Result<()> {
|
pub fn diff(&mut self, from: DatabaseName<'_>, table: &str) -> Result<()> {
|
||||||
let from = from.as_cstring()?;
|
let from = from.as_cstr()?;
|
||||||
let table = str_to_cstring(table)?;
|
let table = str_to_cstring(table)?;
|
||||||
let table = table.as_ptr();
|
let table = table.as_ptr();
|
||||||
unsafe {
|
unsafe {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user