Revert "don't truncate text columns that contain nul bytes"

This reverts commit 004c8f23d4.
This commit is contained in:
Thom Chiovoloni 2020-03-24 10:35:24 -07:00 committed by Thom Chiovoloni
parent edceb01747
commit 8c574be1e3

View File

@ -1,5 +1,6 @@
use std::ffi::CStr;
use std::iter::IntoIterator; use std::iter::IntoIterator;
use std::os::raw::{c_int, c_void}; use std::os::raw::{c_char, c_int, c_void};
#[cfg(feature = "array")] #[cfg(feature = "array")]
use std::rc::Rc; use std::rc::Rc;
use std::slice::from_raw_parts; use std::slice::from_raw_parts;
@ -648,8 +649,7 @@ impl Statement<'_> {
pub(crate) fn value_ref(&self, col: usize) -> ValueRef<'_> { pub(crate) fn value_ref(&self, col: usize) -> ValueRef<'_> {
let raw = unsafe { self.stmt.ptr() }; let raw = unsafe { self.stmt.ptr() };
let kind = self.stmt.column_type(col); match self.stmt.column_type(col) {
match kind {
ffi::SQLITE_NULL => ValueRef::Null, ffi::SQLITE_NULL => ValueRef::Null,
ffi::SQLITE_INTEGER => { ffi::SQLITE_INTEGER => {
ValueRef::Integer(unsafe { ffi::sqlite3_column_int64(raw, col as c_int) }) ValueRef::Integer(unsafe { ffi::sqlite3_column_int64(raw, col as c_int) })
@ -657,7 +657,20 @@ impl Statement<'_> {
ffi::SQLITE_FLOAT => { ffi::SQLITE_FLOAT => {
ValueRef::Real(unsafe { ffi::sqlite3_column_double(raw, col as c_int) }) ValueRef::Real(unsafe { ffi::sqlite3_column_double(raw, col as c_int) })
} }
ffi::SQLITE_TEXT | ffi::SQLITE_BLOB => { ffi::SQLITE_TEXT => {
let s = unsafe {
let text = ffi::sqlite3_column_text(raw, col as c_int);
assert!(
!text.is_null(),
"unexpected SQLITE_TEXT column type with NULL data"
);
CStr::from_ptr(text as *const c_char)
};
let s = s.to_bytes();
ValueRef::Text(s)
}
ffi::SQLITE_BLOB => {
let (blob, len) = unsafe { let (blob, len) = unsafe {
( (
ffi::sqlite3_column_blob(raw, col as c_int), ffi::sqlite3_column_blob(raw, col as c_int),
@ -669,23 +682,16 @@ impl Statement<'_> {
len >= 0, len >= 0,
"unexpected negative return from sqlite3_column_bytes" "unexpected negative return from sqlite3_column_bytes"
); );
if len > 0 {
let bytes = if len > 0 {
assert!( assert!(
!blob.is_null(), !blob.is_null(),
"unexpected SQLITE_BLOB/TEXT column type with NULL data" "unexpected SQLITE_BLOB column type with NULL data"
); );
unsafe { from_raw_parts(blob as *const u8, len as usize) } ValueRef::Blob(unsafe { from_raw_parts(blob as *const u8, len as usize) })
} else { } else {
// The return value from sqlite3_column_blob() for a zero-length BLOB // The return value from sqlite3_column_blob() for a zero-length BLOB
// is a NULL pointer. // is a NULL pointer.
&[] ValueRef::Blob(&[])
};
if kind == ffi::SQLITE_TEXT {
ValueRef::Text(bytes)
} else {
ValueRef::Blob(bytes)
} }
} }
_ => unreachable!("sqlite3_column_type returned invalid value"), _ => unreachable!("sqlite3_column_type returned invalid value"),
@ -734,7 +740,7 @@ pub enum StatementStatus {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::types::ToSql; use crate::types::ToSql;
use crate::{params, Connection, Error, Result, NO_PARAMS}; use crate::{Connection, Error, Result, NO_PARAMS};
#[test] #[test]
fn test_execute_named() { fn test_execute_named() {
@ -1083,21 +1089,4 @@ mod test {
let stmt = conn.prepare(";").unwrap(); let stmt = conn.prepare(";").unwrap();
assert_eq!(0, stmt.column_count()); assert_eq!(0, stmt.column_count());
} }
#[test]
fn test_nul_in_text_column() {
let db = Connection::open_in_memory().unwrap();
db.execute_batch("create table tbl(val text);").unwrap();
let expected = "a\x00b".to_string();
db.execute(
"insert into tbl values (cast(? as text))",
params![expected.as_bytes()],
)
.unwrap();
let text: String = db
.query_row("select val from tbl", NO_PARAMS, |row| row.get(0))
.unwrap();
assert_eq!(text, expected);
}
} }