Skip to content

Commit 6f4c478

Browse files
committed
sqlite: fix NULL handling
1 parent 582e260 commit 6f4c478

File tree

3 files changed

+41
-39
lines changed

3 files changed

+41
-39
lines changed

sqlx-core/src/sqlite/types/mod.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ pub(crate) enum SqliteType {
1818
Float = 2,
1919
Text = 3,
2020
Blob = 4,
21-
Null = 5,
2221

2322
// Non-standard extensions
2423
Boolean,
@@ -52,7 +51,6 @@ impl SqliteTypeInfo {
5251
impl Display for SqliteTypeInfo {
5352
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
5453
f.write_str(match self.r#type {
55-
SqliteType::Null => "NULL",
5654
SqliteType::Text => "TEXT",
5755
SqliteType::Boolean => "BOOLEAN",
5856
SqliteType::Integer => "INTEGER",
@@ -73,9 +71,10 @@ where
7371
T: Decode<'de, Sqlite>,
7472
{
7573
fn decode(value: SqliteValue<'de>) -> crate::Result<Self> {
76-
match value.r#type() {
77-
SqliteType::Null => Ok(None),
78-
_ => <T as Decode<Sqlite>>::decode(value).map(Some),
74+
if value.is_null() {
75+
Ok(None)
76+
} else {
77+
<T as Decode<Sqlite>>::decode(value).map(Some)
7978
}
8079
}
8180
}

sqlx-core/src/sqlite/types/str.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::decode::Decode;
22
use crate::encode::Encode;
3+
use crate::error::UnexpectedNullError;
34
use crate::sqlite::types::{SqliteType, SqliteTypeAffinity};
45
use crate::sqlite::{Sqlite, SqliteArgumentValue, SqliteTypeInfo, SqliteValue};
56
use crate::types::Type;
@@ -31,7 +32,9 @@ impl Encode<Sqlite> for String {
3132

3233
impl<'de> Decode<'de, Sqlite> for &'de str {
3334
fn decode(value: SqliteValue<'de>) -> crate::Result<&'de str> {
34-
Ok(value.text())
35+
value
36+
.text()
37+
.ok_or_else(|| crate::Error::decode(UnexpectedNullError))
3538
}
3639
}
3740

sqlx-core/src/sqlite/value.rs

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,23 @@ use std::str::from_utf8_unchecked;
55

66
use libsqlite3_sys::{
77
sqlite3_column_blob, sqlite3_column_bytes, sqlite3_column_double, sqlite3_column_int,
8-
sqlite3_column_int64, sqlite3_column_text, sqlite3_column_type, SQLITE_BLOB, SQLITE_FLOAT,
9-
SQLITE_INTEGER, SQLITE_NULL, SQLITE_TEXT,
8+
sqlite3_column_int64, sqlite3_column_text, sqlite3_column_type, SQLITE_NULL,
109
};
1110

1211
use crate::sqlite::statement::Statement;
13-
use crate::sqlite::types::SqliteType;
1412

1513
pub struct SqliteValue<'c> {
16-
index: usize,
14+
index: i32,
1715
statement: &'c Statement,
1816
}
1917

2018
impl<'c> SqliteValue<'c> {
2119
#[inline]
2220
pub(super) fn new(statement: &'c Statement, index: usize) -> Self {
23-
Self { statement, index }
21+
Self {
22+
statement,
23+
index: index as i32,
24+
}
2425
}
2526
}
2627

@@ -30,72 +31,71 @@ impl<'c> SqliteValue<'c> {
3031
// These routines return information about a single column of the current result row of a query.
3132

3233
impl<'c> SqliteValue<'c> {
33-
/// Returns the initial data type of the result column.
34-
pub(super) fn r#type(&self) -> SqliteType {
34+
/// Returns true if the value should be intrepreted as NULL.
35+
pub(super) fn is_null(&self) -> bool {
3536
#[allow(unsafe_code)]
36-
let type_code = unsafe { sqlite3_column_type(self.statement.handle(), self.index as i32) };
37-
38-
match type_code {
39-
SQLITE_INTEGER => SqliteType::Integer,
40-
SQLITE_FLOAT => SqliteType::Float,
41-
SQLITE_BLOB => SqliteType::Blob,
42-
SQLITE_NULL => SqliteType::Null,
43-
SQLITE_TEXT => SqliteType::Text,
44-
45-
_ => unreachable!(),
46-
}
37+
let type_code = unsafe { sqlite3_column_type(self.statement.handle(), self.index) };
38+
type_code == SQLITE_NULL
4739
}
4840

4941
/// Returns the 32-bit INTEGER result.
5042
pub(super) fn int(&self) -> i32 {
5143
#[allow(unsafe_code)]
5244
unsafe {
53-
sqlite3_column_int(self.statement.handle(), self.index as i32)
45+
sqlite3_column_int(self.statement.handle(), self.index)
5446
}
5547
}
5648

5749
/// Returns the 64-bit INTEGER result.
5850
pub(super) fn int64(&self) -> i64 {
5951
#[allow(unsafe_code)]
6052
unsafe {
61-
sqlite3_column_int64(self.statement.handle(), self.index as i32)
53+
sqlite3_column_int64(self.statement.handle(), self.index)
6254
}
6355
}
6456

6557
/// Returns the 64-bit, REAL result.
6658
pub(super) fn double(&self) -> f64 {
6759
#[allow(unsafe_code)]
6860
unsafe {
69-
sqlite3_column_double(self.statement.handle(), self.index as i32)
61+
sqlite3_column_double(self.statement.handle(), self.index)
7062
}
7163
}
7264

7365
/// Returns the UTF-8 TEXT result.
74-
pub(super) fn text(&self) -> &'c str {
66+
pub(super) fn text(&self) -> Option<&'c str> {
7567
#[allow(unsafe_code)]
7668
unsafe {
77-
let ptr = sqlite3_column_text(self.statement.handle(), self.index as i32) as *const i8;
78-
79-
debug_assert!(!ptr.is_null());
69+
let ptr = sqlite3_column_text(self.statement.handle(), self.index) as *const i8;
8070

81-
from_utf8_unchecked(CStr::from_ptr(ptr).to_bytes())
71+
if ptr.is_null() {
72+
None
73+
} else {
74+
Some(from_utf8_unchecked(CStr::from_ptr(ptr).to_bytes()))
75+
}
8276
}
8377
}
8478

79+
fn bytes(&self) -> usize {
80+
// Returns the size of the result in bytes.
81+
#[allow(unsafe_code)]
82+
let len = unsafe { sqlite3_column_bytes(self.statement.handle(), self.index) };
83+
len as usize
84+
}
85+
8586
/// Returns the BLOB result.
8687
pub(super) fn blob(&self) -> &'c [u8] {
87-
let index = self.index as i32;
88-
8988
#[allow(unsafe_code)]
90-
let ptr = unsafe { sqlite3_column_blob(self.statement.handle(), index) };
89+
let ptr = unsafe { sqlite3_column_blob(self.statement.handle(), self.index) };
9190

92-
// Returns the size of the BLOB result in bytes.
93-
#[allow(unsafe_code)]
94-
let len = unsafe { sqlite3_column_bytes(self.statement.handle(), index) };
91+
if ptr.is_null() {
92+
// Empty BLOBs are received as null pointers
93+
return &[];
94+
}
9595

9696
#[allow(unsafe_code)]
9797
unsafe {
98-
slice::from_raw_parts(ptr as *const u8, len as usize)
98+
slice::from_raw_parts(ptr as *const u8, self.bytes())
9999
}
100100
}
101101
}

0 commit comments

Comments
 (0)