Skip to content
This repository was archived by the owner on Apr 25, 2023. It is now read-only.

Commit 8be4fab

Browse files
authored
Distinction between int32 and int64 in SQLite (#369)
* Made distinction between INT32 and INT64 types in sqlite * For statements when we know the declaration type, we make a distinction between INT32 and INT64 values * This does not apply with `RETURNING` or implicit values, in these cases we don't know the decl type and we always return INT64 * This is work required for prisma/prisma#12784
1 parent a916d18 commit 8be4fab

File tree

4 files changed

+155
-286
lines changed

4 files changed

+155
-286
lines changed

src/connector/sqlite.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ mod tests {
286286
let result = conn.select(select.clone()).await.unwrap();
287287
let result = result.into_single().unwrap();
288288

289-
assert_eq!(result.get("id").unwrap(), &Value::integer(1));
289+
assert_eq!(result.get("id").unwrap(), &Value::int32(1));
290290
assert_eq!(result.get("txt").unwrap(), &Value::text("henlo"));
291291

292292
// Check that we do get a separate, new database.

src/connector/sqlite/conversion.rs

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::convert::TryFrom;
2+
13
use crate::{
24
ast::Value,
35
connector::{
@@ -129,7 +131,9 @@ impl<'a> GetRow for SqliteRow<'a> {
129131
for (i, column) in self.columns().iter().enumerate() {
130132
let pv = match self.get_ref_unwrap(i) {
131133
ValueRef::Null => match column {
132-
c if c.is_int32() | c.is_int64() | c.is_null() => Value::Int64(None),
134+
// NOTE: A value without decl_type would be Int32(None)
135+
c if c.is_int32() | c.is_null() => Value::Int32(None),
136+
c if c.is_int64() => Value::Int64(None),
133137
c if c.is_text() => Value::Text(None),
134138
c if c.is_bytes() => Value::Bytes(None),
135139
c if c.is_float() => Value::Float(None),
@@ -148,29 +152,43 @@ impl<'a> GetRow for SqliteRow<'a> {
148152

149153
return Err(Error::builder(kind).build());
150154
}
151-
None => Value::Int64(None),
155+
// When we don't know what to do, the default value would be Int32(None)
156+
None => Value::Int32(None),
152157
},
153158
},
154-
ValueRef::Integer(i) => match column {
155-
c if c.is_bool() => {
156-
if i == 0 {
157-
Value::boolean(false)
158-
} else {
159-
Value::boolean(true)
159+
ValueRef::Integer(i) => {
160+
match column {
161+
c if c.is_bool() => {
162+
if i == 0 {
163+
Value::boolean(false)
164+
} else {
165+
Value::boolean(true)
166+
}
160167
}
168+
#[cfg(feature = "chrono")]
169+
c if c.is_date() => {
170+
let dt = chrono::NaiveDateTime::from_timestamp(i / 1000, 0);
171+
Value::date(dt.date())
172+
}
173+
#[cfg(feature = "chrono")]
174+
c if c.is_datetime() => {
175+
let dt = chrono::Utc.timestamp_millis(i);
176+
Value::datetime(dt)
177+
}
178+
c if c.is_int32() => {
179+
if let Ok(converted) = i32::try_from(i) {
180+
Value::int32(converted)
181+
} else {
182+
let msg = format!("Value {} does not fit in an INT column, try migrating the '{}' column type to BIGINT", i, c.name());
183+
let kind = ErrorKind::conversion(msg);
184+
185+
return Err(Error::builder(kind).build());
186+
}
187+
}
188+
// NOTE: When SQLite does not know what type the return is (for example at explicit values and RETURNING statements) we will 'assume' int64
189+
_ => Value::int64(i),
161190
}
162-
#[cfg(feature = "chrono")]
163-
c if c.is_date() => {
164-
let dt = chrono::NaiveDateTime::from_timestamp(i / 1000, 0);
165-
Value::date(dt.date())
166-
}
167-
#[cfg(feature = "chrono")]
168-
c if c.is_datetime() => {
169-
let dt = chrono::Utc.timestamp_millis(i);
170-
Value::datetime(dt)
171-
}
172-
_ => Value::int64(i),
173-
},
191+
}
174192
#[cfg(feature = "bigdecimal")]
175193
ValueRef::Real(f) if column.is_real() => {
176194
use bigdecimal::{BigDecimal, FromPrimitive};

0 commit comments

Comments
 (0)