From 1fee2eb4fd4aa8b77e29384b4355c7b969a76dae Mon Sep 17 00:00:00 2001 From: wangfenjin Date: Wed, 29 Sep 2021 10:39:16 +0800 Subject: [PATCH] support hugeint Change-Id: I0162316880d07e8760a749cd9893a9497014e3a5 --- src/row.rs | 4 ++++ src/statement.rs | 11 +++++++---- src/types/from_sql.rs | 14 ++++++++++++++ 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/row.rs b/src/row.rs index 2aa15628..63aa6815 100644 --- a/src/row.rs +++ b/src/row.rs @@ -481,6 +481,10 @@ impl<'stmt> Row<'stmt> { if array.is_null(row) { return ValueRef::Null; } + // hugeint: d:38,0 + if array.scale() == 0 { + return ValueRef::HugeInt(array.value(row)); + } ValueRef::Decimal(Decimal::from_i128_with_scale(array.value(row), array.scale() as u32)) } DataType::Timestamp(unit, _) if *unit == TimeUnit::Second => { diff --git a/src/statement.rs b/src/statement.rs index a8eccfdd..b466af52 100644 --- a/src/statement.rs +++ b/src/statement.rs @@ -419,10 +419,13 @@ impl Statement<'_> { ValueRef::SmallInt(i) => unsafe { ffi::duckdb_bind_int16(ptr, col as u64, i) }, ValueRef::Int(i) => unsafe { ffi::duckdb_bind_int32(ptr, col as u64, i) }, ValueRef::BigInt(i) => unsafe { ffi::duckdb_bind_int64(ptr, col as u64, i) }, - - // FIXME - ValueRef::HugeInt(i) => unsafe { ffi::duckdb_bind_int64(ptr, col as u64, i as i64) }, - + ValueRef::HugeInt(i) => unsafe { + let hi = ffi::duckdb_hugeint { + lower: i as u64, + upper: (i >> 64) as i64, + }; + ffi::duckdb_bind_hugeint(ptr, col as u64, hi) + }, ValueRef::Float(r) => unsafe { ffi::duckdb_bind_float(ptr, col as u64, r) }, ValueRef::Double(r) => unsafe { ffi::duckdb_bind_double(ptr, col as u64, r) }, ValueRef::Text(s) => unsafe { diff --git a/src/types/from_sql.rs b/src/types/from_sql.rs index 3257cc37..7a5bb15d 100644 --- a/src/types/from_sql.rs +++ b/src/types/from_sql.rs @@ -313,6 +313,20 @@ mod test { Ok(()) } + // This test asserts that i128s above/below the i64 max/min can written and retrieved properly. + #[test] + fn test_hugeint_max_min() -> Result<()> { + let db = Connection::open_in_memory()?; + db.execute("CREATE TABLE huge_int (u1 hugeint, u2 hugeint);", [])?; + // Min/Max value defined in here: https://duckdb.org/docs/sql/data_types/numeric + let i128max: i128 = i128::MAX; + let i128min: i128 = i128::MIN + 1; + db.execute("INSERT INTO huge_int VALUES (?, ?);", [&i128max, &i128min])?; + let v = db.query_row("SELECT * FROM huge_int", [], |row| <(i128, i128)>::try_from(row))?; + assert_eq!(v, (i128max, i128min)); + Ok(()) + } + #[test] fn test_integral_ranges() -> Result<()> { let db = Connection::open_in_memory()?;