mirror of
https://github.com/isar/rusqlite.git
synced 2024-11-27 03:51:38 +08:00
Merge pull request #584 from gwenn/empty_query
Segmentation fault on `prepare_cached` with an empty query
This commit is contained in:
commit
4923d8f8da
11
src/cache.rs
11
src/cache.rs
@ -135,9 +135,12 @@ impl StatementCache {
|
|||||||
|
|
||||||
// Return a statement to the cache.
|
// Return a statement to the cache.
|
||||||
fn cache_stmt(&self, stmt: RawStatement) {
|
fn cache_stmt(&self, stmt: RawStatement) {
|
||||||
|
if stmt.is_null() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
let mut cache = self.0.borrow_mut();
|
let mut cache = self.0.borrow_mut();
|
||||||
stmt.clear_bindings();
|
stmt.clear_bindings();
|
||||||
let sql = String::from_utf8_lossy(stmt.sql().to_bytes())
|
let sql = String::from_utf8_lossy(stmt.sql().unwrap().to_bytes())
|
||||||
.trim()
|
.trim()
|
||||||
.to_string();
|
.to_string();
|
||||||
cache.insert(sql, stmt);
|
cache.insert(sql, stmt);
|
||||||
@ -339,4 +342,10 @@ mod test {
|
|||||||
}
|
}
|
||||||
assert_eq!(1, cache.len());
|
assert_eq!(1, cache.len());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_empty_stmt() {
|
||||||
|
let conn = Connection::open_in_memory().unwrap();
|
||||||
|
conn.prepare_cached("").unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,9 +90,17 @@ impl InnerConnection {
|
|||||||
} else {
|
} else {
|
||||||
let mut e = error_from_handle(db, r);
|
let mut e = error_from_handle(db, r);
|
||||||
if let Error::SqliteFailure(
|
if let Error::SqliteFailure(
|
||||||
ffi::Error{code: ffi::ErrorCode::CannotOpen, extended_code: _}, Some(msg)) = e {
|
ffi::Error {
|
||||||
|
code: ffi::ErrorCode::CannotOpen,
|
||||||
|
extended_code: _,
|
||||||
|
},
|
||||||
|
Some(msg),
|
||||||
|
) = e
|
||||||
|
{
|
||||||
e = Error::SqliteFailure(
|
e = Error::SqliteFailure(
|
||||||
ffi::Error::new(r), Some(format!("{}: {}", msg, c_path.to_string_lossy())));
|
ffi::Error::new(r),
|
||||||
|
Some(format!("{}: {}", msg, c_path.to_string_lossy())),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
ffi::sqlite3_close(db);
|
ffi::sqlite3_close(db);
|
||||||
e
|
e
|
||||||
@ -254,8 +262,10 @@ impl InnerConnection {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
// If there is an error, *ppStmt is set to NULL.
|
||||||
self.decode_result(r)?;
|
self.decode_result(r)?;
|
||||||
|
// If the input text contains no SQL (if the input is an empty string or a
|
||||||
|
// comment) then *ppStmt is set to NULL.
|
||||||
let c_stmt: *mut ffi::sqlite3_stmt = unsafe { c_stmt.assume_init() };
|
let c_stmt: *mut ffi::sqlite3_stmt = unsafe { c_stmt.assume_init() };
|
||||||
let c_tail: *const c_char = unsafe { c_tail.assume_init() };
|
let c_tail: *const c_char = unsafe { c_tail.assume_init() };
|
||||||
// TODO ignore spaces, comments, ... at the end
|
// TODO ignore spaces, comments, ... at the end
|
||||||
|
@ -966,7 +966,12 @@ mod test {
|
|||||||
if let Error::SqliteFailure(e, Some(msg)) = err {
|
if let Error::SqliteFailure(e, Some(msg)) = err {
|
||||||
assert_eq!(ErrorCode::CannotOpen, e.code);
|
assert_eq!(ErrorCode::CannotOpen, e.code);
|
||||||
assert_eq!(ffi::SQLITE_CANTOPEN, e.extended_code);
|
assert_eq!(ffi::SQLITE_CANTOPEN, e.extended_code);
|
||||||
assert!(msg.contains(filename), "error message '{}' does not contain '{}'", msg, filename);
|
assert!(
|
||||||
|
msg.contains(filename),
|
||||||
|
"error message '{}' does not contain '{}'",
|
||||||
|
msg,
|
||||||
|
filename
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
panic!("SqliteFailure expected");
|
panic!("SqliteFailure expected");
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,10 @@ impl RawStatement {
|
|||||||
RawStatement(stmt, tail)
|
RawStatement(stmt, tail)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_null(&self) -> bool {
|
||||||
|
self.0.is_null()
|
||||||
|
}
|
||||||
|
|
||||||
pub unsafe fn ptr(&self) -> *mut ffi::sqlite3_stmt {
|
pub unsafe fn ptr(&self) -> *mut ffi::sqlite3_stmt {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
@ -95,8 +99,12 @@ impl RawStatement {
|
|||||||
unsafe { ffi::sqlite3_clear_bindings(self.0) }
|
unsafe { ffi::sqlite3_clear_bindings(self.0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sql(&self) -> &CStr {
|
pub fn sql(&self) -> Option<&CStr> {
|
||||||
unsafe { CStr::from_ptr(ffi::sqlite3_sql(self.0)) }
|
if self.0.is_null() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(unsafe { CStr::from_ptr(ffi::sqlite3_sql(self.0)) })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn finalize(mut self) -> c_int {
|
pub fn finalize(mut self) -> c_int {
|
||||||
|
@ -625,7 +625,11 @@ impl Into<RawStatement> for Statement<'_> {
|
|||||||
|
|
||||||
impl fmt::Debug for Statement<'_> {
|
impl fmt::Debug for Statement<'_> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let sql = str::from_utf8(self.stmt.sql().to_bytes());
|
let sql = if self.stmt.is_null() {
|
||||||
|
Ok("")
|
||||||
|
} else {
|
||||||
|
str::from_utf8(self.stmt.sql().unwrap().to_bytes())
|
||||||
|
};
|
||||||
f.debug_struct("Statement")
|
f.debug_struct("Statement")
|
||||||
.field("conn", self.conn)
|
.field("conn", self.conn)
|
||||||
.field("stmt", &self.stmt)
|
.field("stmt", &self.stmt)
|
||||||
@ -1058,4 +1062,35 @@ mod test {
|
|||||||
db.query_row("SELECT ?1, ?2, ?3", data.iter(), |row| row.get::<_, u8>(0))
|
db.query_row("SELECT ?1, ?2, ?3", data.iter(), |row| row.get::<_, u8>(0))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_empty_stmt() {
|
||||||
|
let conn = Connection::open_in_memory().unwrap();
|
||||||
|
let mut stmt = conn.prepare("").unwrap();
|
||||||
|
assert_eq!(0, stmt.column_count());
|
||||||
|
assert!(stmt.parameter_index("test").is_ok());
|
||||||
|
assert!(stmt.step().is_err());
|
||||||
|
stmt.reset();
|
||||||
|
assert!(stmt.execute(NO_PARAMS).is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_comment_stmt() {
|
||||||
|
let conn = Connection::open_in_memory().unwrap();
|
||||||
|
conn.prepare("/*SELECT 1;*/").unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_comment_and_sql_stmt() {
|
||||||
|
let conn = Connection::open_in_memory().unwrap();
|
||||||
|
let stmt = conn.prepare("/*...*/ SELECT 1;").unwrap();
|
||||||
|
assert_eq!(1, stmt.column_count());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_semi_colon_stmt() {
|
||||||
|
let conn = Connection::open_in_memory().unwrap();
|
||||||
|
let stmt = conn.prepare(";").unwrap();
|
||||||
|
assert_eq!(0, stmt.column_count());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user