diff --git a/CHANGELOG.md b/CHANGELOG.md index 9eaa7b435e..8bf3887cde 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,11 @@ 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.37 + +- Fix encoding of `DateTime` in SQLite. It used to be encoded as an RFC3339 string (with a 'T' between date and time), + which is inconsistent with the format used by CURRENT_TIMESTAMP in SQLite. This could easily result in nasty bugs where comparing datetimes generated by SQLite and datetimes generated from rust would return incorrect results. + ## 0.6.36 - Fix decoding of MySQL `BIT` type as boolean diff --git a/Cargo.lock b/Cargo.lock index 3acfd93b0b..0d39404f55 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -245,7 +245,7 @@ checksum = "9343dc5acf07e79ff82d0c37899f079db3534d99f189a1837c8e549c99405bec" dependencies = [ "futures-util", "native-tls", - "thiserror", + "thiserror 1.0.69", "url", ] @@ -549,9 +549,9 @@ dependencies = [ [[package]] name = "borsh" -version = "1.5.2" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5327f6c99920069d1fe374aa743be1af0031dea9f250852cdf1ae6a0861ee24" +checksum = "2506947f73ad44e344215ccd6403ac2ae18cd8e046e581a441bf8d199f257f03" dependencies = [ "borsh-derive", "cfg_aliases 0.2.1", @@ -559,9 +559,9 @@ dependencies = [ [[package]] name = "borsh-derive" -version = "1.5.2" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10aedd8f1a81a8aafbfde924b0e3061cd6fedd6f6bbcfc6a76e6fd426d7bfe26" +checksum = "c2593a3b8b938bd68373196c9832f516be11fa487ef4ae745eb282e6a56a7244" dependencies = [ "once_cell", "proc-macro-crate", @@ -572,9 +572,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" +checksum = "1a68f1f47cdf0ec8ee4b941b2eee2a80cb796db73118c0dd09ac63fbe405be22" dependencies = [ "memchr", "serde", @@ -659,9 +659,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.1.36" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baee610e9452a8f6f0a1b6194ec09ff9e2d85dea54432acdae41aa0761c95d70" +checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" dependencies = [ "jobserver", "libc", @@ -818,9 +818,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +checksum = "0ca741a962e1b0bff6d724a1a0958b686406e853bb14061f218562e1896f95e6" dependencies = [ "libc", ] @@ -922,9 +922,9 @@ dependencies = [ [[package]] name = "csv" -version = "1.3.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" +checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" dependencies = [ "csv-core", "itoa", @@ -1897,9 +1897,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "7a73e9fe3c49d7afb2ace819fa181a287ce54a0983eda4e0eb05c22f82ffe534" [[package]] name = "jobserver" @@ -1953,9 +1953,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.162" +version = "0.2.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" +checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f" [[package]] name = "libgit2-sys" @@ -2347,9 +2347,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "300.4.0+3.4.0" +version = "300.4.1+3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a709e02f2b4aca747929cca5ed248880847c650233cf8b8cdc48f40aaf4898a6" +checksum = "faa4eac4138c62414b5622d1b31c5c304f34b406b013c079c2bbc652fdd6678c" dependencies = [ "cc", ] @@ -2807,7 +2807,7 @@ checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", "libredox", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -2824,9 +2824,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -2958,9 +2958,9 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustix" -version = "0.38.39" +version = "0.38.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "375116bee2be9ed569afe2154ea6a99dfdffd257f533f187498c2a8f5feaf4ee" +checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" dependencies = [ "bitflags 2.6.0", "errno", @@ -3050,9 +3050,9 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" dependencies = [ "windows-sys 0.59.0", ] @@ -3084,9 +3084,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.12.0" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" +checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2" dependencies = [ "core-foundation-sys", "libc", @@ -3103,9 +3103,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.214" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] @@ -3122,9 +3122,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.214" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", @@ -3133,9 +3133,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.132" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "itoa", "memchr", @@ -3313,7 +3313,7 @@ dependencies = [ [[package]] name = "sqlx-cli" -version = "0.6.36" +version = "0.6.37" dependencies = [ "anyhow", "async-trait", @@ -3338,7 +3338,7 @@ dependencies = [ [[package]] name = "sqlx-core-oldapi" -version = "0.6.36" +version = "0.6.37" dependencies = [ "ahash 0.8.11", "atoi", @@ -3397,7 +3397,7 @@ dependencies = [ "sqlx-oldapi", "sqlx-rt-oldapi", "stringprep", - "thiserror", + "thiserror 2.0.3", "time", "tokio", "tokio-stream", @@ -3434,7 +3434,7 @@ dependencies = [ "serde_json", "serde_with", "sqlx-oldapi", - "thiserror", + "thiserror 1.0.69", "time", "tokio", "tower", @@ -3500,7 +3500,7 @@ dependencies = [ [[package]] name = "sqlx-macros-oldapi" -version = "0.6.36" +version = "0.6.37" dependencies = [ "dotenvy", "either", @@ -3520,7 +3520,7 @@ dependencies = [ [[package]] name = "sqlx-oldapi" -version = "0.6.36" +version = "0.6.37" dependencies = [ "anyhow", "async-std", @@ -3547,7 +3547,7 @@ dependencies = [ [[package]] name = "sqlx-rt-oldapi" -version = "0.6.36" +version = "0.6.37" dependencies = [ "async-native-tls", "async-std", @@ -3748,18 +3748,38 @@ checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" [[package]] name = "thiserror" -version = "1.0.68" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02dd99dc800bbb97186339685293e1cc5d9df1f8fae2d0aecd9ff1c77efea892" +checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" dependencies = [ - "thiserror-impl", + "thiserror-impl 2.0.3", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", ] [[package]] name = "thiserror-impl" -version = "1.0.68" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7c61ec9a6f64d2793d8a45faba21efbe3ced62a886d44c36a009b2b519b4c7e" +checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" dependencies = [ "proc-macro2", "quote", @@ -4055,9 +4075,9 @@ checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-normalization" diff --git a/Cargo.toml b/Cargo.toml index fe7a53f728..9c02bff1fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ members = [ [package] name = "sqlx-oldapi" -version = "0.6.36" +version = "0.6.37" license = "MIT OR Apache-2.0" readme = "README.md" repository = "https://github.com/lovasoa/sqlx" @@ -125,8 +125,8 @@ bstr = ["sqlx-core/bstr"] git2 = ["sqlx-core/git2"] [dependencies] -sqlx-core = { package = "sqlx-core-oldapi", version = "0.6.36", path = "sqlx-core", default-features = false } -sqlx-macros = { package = "sqlx-macros-oldapi", version = "0.6.36", path = "sqlx-macros", default-features = false, optional = true } +sqlx-core = { package = "sqlx-core-oldapi", version = "0.6.37", path = "sqlx-core", default-features = false } +sqlx-macros = { package = "sqlx-macros-oldapi", version = "0.6.37", path = "sqlx-macros", default-features = false, optional = true } [dev-dependencies] anyhow = "1.0.52" diff --git a/examples/postgres/axum-social-with-tests/Cargo.toml b/examples/postgres/axum-social-with-tests/Cargo.toml index b7922bfe2d..d03d44b139 100644 --- a/examples/postgres/axum-social-with-tests/Cargo.toml +++ b/examples/postgres/axum-social-with-tests/Cargo.toml @@ -8,7 +8,7 @@ edition = "2021" [dependencies] # Primary crates axum = { version = "0.5.13", features = ["macros"] } -sqlx = { package = "sqlx-oldapi", version = "0.6.36", path = "../../../", features = ["runtime-tokio-rustls", "postgres", "time", "uuid"] } +sqlx = { package = "sqlx-oldapi", version = "0.6.37", path = "../../../", features = ["runtime-tokio-rustls", "postgres", "time", "uuid"] } tokio = { version = "1.20.1", features = ["rt-multi-thread", "macros"] } # Important secondary crates diff --git a/sqlx-cli/Cargo.toml b/sqlx-cli/Cargo.toml index b2c0e4e054..15b8114e7c 100644 --- a/sqlx-cli/Cargo.toml +++ b/sqlx-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sqlx-cli" -version = "0.6.36" +version = "0.6.37" description = "Command-line utility for SQLx, the Rust SQL toolkit." edition = "2021" readme = "README.md" diff --git a/sqlx-core/Cargo.toml b/sqlx-core/Cargo.toml index a3ea2fde22..c1e6564123 100644 --- a/sqlx-core/Cargo.toml +++ b/sqlx-core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sqlx-core-oldapi" -version = "0.6.36" +version = "0.6.37" repository = "https://github.com/lovasoa/sqlx" description = "Core of SQLx, the rust SQL toolkit. Not intended to be used directly." license = "MIT OR Apache-2.0" @@ -101,7 +101,7 @@ offline = ["serde", "either/serde"] paste = "1.0.6" ahash = "0.8.3" atoi = "2.0.0" -sqlx-rt = { path = "../sqlx-rt", version = "0.6.36", package = "sqlx-rt-oldapi" } +sqlx-rt = { path = "../sqlx-rt", version = "0.6.37", package = "sqlx-rt-oldapi" } base64 = { version = "0.22", default-features = false, optional = true, features = ["std"] } bigdecimal_ = { version = "0.4.1", optional = true, package = "bigdecimal" } rust_decimal = { version = "1.19.0", optional = true } @@ -151,7 +151,7 @@ serde_json = { version = "1.0.73", features = ["raw_value"], optional = true } sha1 = { version = "0.10.1", default-features = false, optional = true } sha2 = { version = "0.10.0", default-features = false, optional = true } sqlformat = "0.2.0" -thiserror = "1.0.30" +thiserror = "2.0.3" time = { version = "0.3.2", features = ["macros", "formatting", "parsing"], optional = true } tokio-stream = { version = "0.1.8", features = ["fs"], optional = true } tokio-util = { version = "0.7.0", features = ["compat"], default-features = false, optional = true } diff --git a/sqlx-core/src/sqlite/types/chrono.rs b/sqlx-core/src/sqlite/types/chrono.rs index 373b564070..b180f95535 100644 --- a/sqlx-core/src/sqlite/types/chrono.rs +++ b/sqlx-core/src/sqlite/types/chrono.rs @@ -7,9 +7,8 @@ use crate::{ sqlite::{type_info::DataType, Sqlite, SqliteArgumentValue, SqliteTypeInfo, SqliteValueRef}, types::Type, }; -use chrono::{ - DateTime, Local, NaiveDate, NaiveDateTime, NaiveTime, Offset, SecondsFormat, TimeZone, Utc, -}; +use chrono::format::{Fixed, Item, Numeric, Pad}; +use chrono::{DateTime, Local, NaiveDate, NaiveDateTime, NaiveTime, Offset, TimeZone, Utc}; impl Type for DateTime { fn type_info() -> SqliteTypeInfo { @@ -62,7 +61,26 @@ where Tz::Offset: core::fmt::Display, { fn encode_by_ref(&self, buf: &mut Vec>) -> IsNull { - Encode::::encode(self.to_rfc3339_opts(SecondsFormat::AutoSi, false), buf) + const OFFSET_DATE_TIME: [Item<'static>; 13] = [ + Item::Numeric(Numeric::Year, Pad::Zero), + Item::Literal("-"), + Item::Numeric(Numeric::Month, Pad::Zero), + Item::Literal("-"), + Item::Numeric(Numeric::Day, Pad::Zero), + Item::Literal(" "), + Item::Numeric(Numeric::Hour, Pad::Zero), + Item::Literal(":"), + Item::Numeric(Numeric::Minute, Pad::Zero), + Item::Literal(":"), + Item::Numeric(Numeric::Second, Pad::Zero), + Item::Fixed(Fixed::Nanosecond), + Item::Fixed(Fixed::TimezoneOffsetColon), + ]; + Encode::::encode( + self.format_with_items(OFFSET_DATE_TIME.into_iter()) + .to_string(), + buf, + ) } } diff --git a/sqlx-core/src/sqlite/types/time.rs b/sqlx-core/src/sqlite/types/time.rs index 1984cc6a61..bac568c671 100644 --- a/sqlx-core/src/sqlite/types/time.rs +++ b/sqlx-core/src/sqlite/types/time.rs @@ -55,7 +55,7 @@ impl Type for Time { impl Encode<'_, Sqlite> for OffsetDateTime { fn encode_by_ref(&self, buf: &mut Vec>) -> IsNull { - Encode::::encode(self.format(&Rfc3339).unwrap(), buf) + Encode::::encode(self.format(formats::OFFSET_DATE_TIME).unwrap(), buf) } } @@ -263,6 +263,7 @@ mod formats { Optional(&SECOND), Optional(&Literal(b".")), Optional(&SUBSECOND), + Optional(&Literal(b" ")), Optional(&OFFSET_HOUR), Optional(&Literal(b":")), Optional(&OFFSET_MINUTE), diff --git a/sqlx-macros/Cargo.toml b/sqlx-macros/Cargo.toml index 287c7f4692..2f26e5b210 100644 --- a/sqlx-macros/Cargo.toml +++ b/sqlx-macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sqlx-macros-oldapi" -version = "0.6.36" +version = "0.6.37" repository = "https://github.com/lovasoa/sqlx" description = "Macros for SQLx, the rust SQL toolkit. Not intended to be used directly." license = "MIT OR Apache-2.0" @@ -75,8 +75,8 @@ heck = { version = "0.5" } either = "1.6.1" once_cell = "1.9.0" proc-macro2 = { version = "1.0.36", default-features = false } -sqlx-core = { package = "sqlx-core-oldapi", version = "0.6.36", default-features = false, features = ["any"], path = "../sqlx-core" } -sqlx-rt = { version = "0.6.36", default-features = false, path = "../sqlx-rt", package = "sqlx-rt-oldapi" } +sqlx-core = { package = "sqlx-core-oldapi", version = "0.6.37", default-features = false, features = ["any"], path = "../sqlx-core" } +sqlx-rt = { version = "0.6.37", default-features = false, path = "../sqlx-rt", package = "sqlx-rt-oldapi" } serde = { version = "1.0.132", features = ["derive"], optional = true } serde_json = { version = "1.0.73", optional = true } sha2 = { version = "0.10.0", optional = true } diff --git a/sqlx-rt/Cargo.toml b/sqlx-rt/Cargo.toml index 8f801a9668..63225858f9 100644 --- a/sqlx-rt/Cargo.toml +++ b/sqlx-rt/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sqlx-rt-oldapi" -version = "0.6.36" +version = "0.6.37" repository = "https://github.com/launchbadge/sqlx" license = "MIT OR Apache-2.0" description = "Runtime abstraction used by SQLx, the Rust SQL toolkit. Not intended to be used directly." diff --git a/test.sh b/test.sh index db6118588c..1d60908271 100755 --- a/test.sh +++ b/test.sh @@ -7,3 +7,5 @@ DATABASE_URL='mssql://sa:Password123!@localhost/sqlx' cargo test --features any, docker compose -f tests/docker-compose.yml run -it -p 3306:3306 --name mysql_8 mysql_8 DATABASE_URL='mysql://root:password@localhost/sqlx' cargo test --features any,mysql,macros,all-types,runtime-actix-rustls -- + +DATABASE_URL='sqlite://./tests/sqlite/sqlite.db' cargo test --features any,sqlite,macros,all-types,runtime-actix-rustls -- \ No newline at end of file diff --git a/tests/sqlite/types.rs b/tests/sqlite/types.rs index e490e061dc..3dad6d8f29 100644 --- a/tests/sqlite/types.rs +++ b/tests/sqlite/types.rs @@ -107,8 +107,24 @@ mod chrono { )); test_type!(chrono_date_time_fixed_offset>(Sqlite, "SELECT datetime({0}) is datetime(?), {0}, ?", - "'2016-11-08T03:50:23-05:00'" == DateTime::parse_from_rfc3339("2016-11-08T03:50:23-05:00").unwrap() + "'2016-11-08T03:50:23-05:00'" == DateTime::parse_from_rfc3339("2016-11-08T03:50:23-05:00").unwrap(), + "'2024-11-08 03:50:23-05:00'" == DateTime::parse_from_rfc3339("2024-11-08T03:50:23-05:00").unwrap() )); + + #[sqlx_macros::test] + async fn it_fromats_datetime_with_space() -> anyhow::Result<()> { + let mut conn = new::().await?; + + let value = sqlx_oldapi::query("select ?") + .bind(DateTime::parse_from_rfc3339("2024-01-08T03:50:23-05:00").unwrap()) + .try_map(|row: SqliteRow| row.try_get::(0)) + .fetch_one(&mut conn) + .await?; + + assert_eq!(value, "2024-01-08 03:50:23-05:00"); + + Ok(()) + } } #[cfg(feature = "time")]