Skip to content

Commit

Permalink
new sqlite implementations
Browse files Browse the repository at this point in the history
  • Loading branch information
lovasoa committed Aug 11, 2023
1 parent d29f523 commit 0b2cb9b
Show file tree
Hide file tree
Showing 10 changed files with 100 additions and 10 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## 0.6.11
- more encode and decode implementations for sqlite (decimal, bigdecimal, date)

## 0.6.10
- add support for Json in mssql
- fix decoding MySQL DECIMAL values as f64 (used to provoke a panic)
Expand Down
33 changes: 33 additions & 0 deletions sqlx-core/src/sqlite/types/bigdecimal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use crate::decode::Decode;
use crate::encode::{Encode, IsNull};
use crate::error::BoxDynError;
use crate::sqlite::{
type_info::DataType, Sqlite, SqliteArgumentValue, SqliteTypeInfo, SqliteValueRef,
};
use crate::types::Type;
use bigdecimal::BigDecimal;

impl Type<Sqlite> for BigDecimal {
fn type_info() -> SqliteTypeInfo {
SqliteTypeInfo(DataType::Text)
}

fn compatible(ty: &SqliteTypeInfo) -> bool {
<&str as Type<Sqlite>>::compatible(ty)
}
}

impl Encode<'_, Sqlite> for BigDecimal {
fn encode_by_ref(&self, buf: &mut Vec<SqliteArgumentValue<'_>>) -> IsNull {
let string_value = self.to_string();
Encode::<Sqlite>::encode(string_value, buf)
}
}

impl Decode<'_, Sqlite> for BigDecimal {
fn decode(value: SqliteValueRef<'_>) -> Result<Self, BoxDynError> {
let string_value = <&str as Decode<Sqlite>>::decode(value)?;

string_value.parse().map_err(Into::into)
}
}
9 changes: 7 additions & 2 deletions sqlx-core/src/sqlite/types/chrono.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::types::chrono::FixedOffset;
use crate::value::ValueRef;
use crate::{
decode::Decode,
encode::{Encode, IsNull},
Expand Down Expand Up @@ -174,7 +173,13 @@ impl<'r> Decode<'r, Sqlite> for NaiveDateTime {

impl<'r> Decode<'r, Sqlite> for NaiveDate {
fn decode(value: SqliteValueRef<'r>) -> Result<Self, BoxDynError> {
Ok(NaiveDate::parse_from_str(value.text()?, "%F")?)
let txt = value.text()?;
for fmt in ["%F", "%x", "%Y%m%d"] {
if let Ok(dt) = NaiveDate::parse_from_str(txt, fmt) {
return Ok(dt);
}
}
Err(format!("invalid date: {}", txt).into())
}
}

Expand Down
42 changes: 42 additions & 0 deletions sqlx-core/src/sqlite/types/decimal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use bigdecimal_::FromPrimitive;
use rust_decimal::Decimal;

use crate::decode::Decode;
use crate::encode::{Encode, IsNull};
use crate::error::BoxDynError;
use crate::sqlite::{
type_info::DataType, Sqlite, SqliteArgumentValue, SqliteTypeInfo, SqliteValueRef,
};
use crate::types::Type;

impl Type<Sqlite> for Decimal {
fn type_info() -> SqliteTypeInfo {
SqliteTypeInfo(DataType::Text)
}

fn compatible(ty: &SqliteTypeInfo) -> bool {
<&str as Type<Sqlite>>::compatible(ty)
|| <f64 as Type<Sqlite>>::compatible(ty)
|| <i64 as Type<Sqlite>>::compatible(ty)
}
}

impl Encode<'_, Sqlite> for Decimal {
fn encode_by_ref(&self, buf: &mut Vec<SqliteArgumentValue<'_>>) -> IsNull {
let string_value = self.to_string();
Encode::<Sqlite>::encode(string_value, buf)
}
}

impl Decode<'_, Sqlite> for Decimal {
fn decode(value: SqliteValueRef<'_>) -> Result<Self, BoxDynError> {
match value.type_info().0 {
DataType::Float => Ok(Decimal::from_f64(value.double()).ok_or("bad float")?),
DataType::Int | DataType::Int64 => Ok(Decimal::from(value.int64())),
_ => {
let string_value = <&str as Decode<Sqlite>>::decode(value)?;
string_value.parse().map_err(Into::into)
}
}
}
}
4 changes: 4 additions & 0 deletions sqlx-core/src/sqlite/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,14 @@
//! a potentially `NULL` value from SQLite.
//!

#[cfg(feature = "bigdecimal")]
mod bigdecimal;
mod bool;
mod bytes;
#[cfg(feature = "chrono")]
mod chrono;
#[cfg(feature = "decimal")]
mod decimal;
mod float;
mod int;
#[cfg(feature = "json")]
Expand Down
1 change: 0 additions & 1 deletion sqlx-core/src/sqlite/types/time.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use crate::value::ValueRef;
use crate::{
decode::Decode,
encode::{Encode, IsNull},
Expand Down
8 changes: 7 additions & 1 deletion sqlx-core/src/sqlite/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ impl<'r> SqliteValueRef<'r> {
SqliteValueData::Value(v) => v.text(),
}
}

pub(super) fn type_info(&self) -> SqliteTypeInfo {
match self.0 {
SqliteValueData::Value(v) => v.type_info.clone(),
}
}
}

impl<'r> ValueRef<'r> for SqliteValueRef<'r> {
Expand Down Expand Up @@ -175,7 +181,7 @@ impl<'r> From<SqliteValueRef<'r>> for crate::any::AnyValueRef<'r> {
#[inline]
fn from(value: SqliteValueRef<'r>) -> Self {
crate::any::AnyValueRef {
type_info: value.type_info().clone().into_owned().into(),
type_info: value.type_info().into(),
kind: crate::any::value::AnyValueRefKind::Sqlite(value),
}
}
Expand Down
6 changes: 3 additions & 3 deletions tests/any/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ async fn it_has_all_the_types() -> anyhow::Result<()> {
#[cfg(feature = "chrono")]
#[sqlx_macros::test]
async fn it_has_chrono() -> anyhow::Result<()> {
use sqlx_oldapi::types::chrono::{DateTime, Utc};
use sqlx_oldapi::types::chrono::NaiveDate;
assert_eq!(
DateTime::parse_from_rfc3339("2020-01-02T03:04:05Z")?,
get_val::<DateTime<Utc>>("CAST('2020-01-02 03:04:05' AS DATETIME)").await?
NaiveDate::from_ymd_opt(2020, 1, 2).unwrap(),
get_val::<NaiveDate>("CAST('20200102' AS DATE)").await?
);
Ok(())
}
Expand Down
Binary file modified tests/sqlite/sqlite.db
Binary file not shown.
4 changes: 1 addition & 3 deletions tests/sqlite/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,7 @@ mod json_tests {
#[cfg(feature = "chrono")]
mod chrono {
use super::*;
use sqlx_oldapi::types::chrono::{
DateTime, FixedOffset, NaiveDate, NaiveDateTime, TimeZone, Utc,
};
use sqlx_oldapi::types::chrono::{DateTime, FixedOffset, NaiveDate, NaiveDateTime, Utc};

test_type!(chrono_naive_date_time<NaiveDateTime>(Sqlite, "SELECT datetime({0}) is datetime(?), {0}, ?",
"'2019-01-02 05:10:20'" == NaiveDate::from_ymd_opt(2019, 1, 2).unwrap().and_hms_opt(5, 10, 20).unwrap()
Expand Down

0 comments on commit 0b2cb9b

Please sign in to comment.