diff --git a/CHANGELOG.md b/CHANGELOG.md index 737dd95..a4fa975 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- upgrade sqlx dependency from 0.8 to 0.9 +- adapt tracing instrumentation for sqlx 0.9's consuming `Execute` API and `SqlStr` type (queries are decomposed and reconstructed via `prepare_query` before execution) + +### Added + +- add `offline` feature to enable `Executor::describe` tracing for compile-time `query!` / offline mode (sqlx 0.9 gates `describe` behind its own offline support; enable with `sqlx-tracing/offline` alongside your database feature, e.g. `features = ["postgres", "offline"]`) + +### Fixed + +- gate `describe` implementations behind `offline` so the crate builds without enabling sqlx's offline machinery by default (fixes `cargo publish` verify failures) + ## [0.2.1](https://github.com/jdrouet/sqlx-tracing/compare/v0.2.0...v0.2.1) - 2026-04-26 ### Added diff --git a/Cargo.lock b/Cargo.lock index 4e70428..24eb02b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -157,12 +157,6 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" -[[package]] -name = "base64ct" -version = "1.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" - [[package]] name = "bitflags" version = "2.11.1" @@ -181,6 +175,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-buffer" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" +dependencies = [ + "hybrid-array", +] + [[package]] name = "bollard" version = "0.19.4" @@ -292,6 +295,17 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "chacha20" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "rand_core 0.10.1", +] + [[package]] name = "chrono" version = "0.4.44" @@ -304,6 +318,12 @@ dependencies = [ "windows-link", ] +[[package]] +name = "cmov" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" + [[package]] name = "concurrent-queue" version = "2.5.0" @@ -313,12 +333,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "const-oid" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" - [[package]] name = "core-foundation" version = "0.10.1" @@ -344,6 +358,15 @@ dependencies = [ "libc", ] +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + [[package]] name = "crc" version = "3.4.0" @@ -384,6 +407,24 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-common" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" +dependencies = [ + "hybrid-array", +] + +[[package]] +name = "ctutils" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" +dependencies = [ + "cmov", +] + [[package]] name = "darling" version = "0.23.0" @@ -418,17 +459,6 @@ dependencies = [ "syn", ] -[[package]] -name = "der" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" -dependencies = [ - "const-oid", - "pem-rfc7468", - "zeroize", -] - [[package]] name = "deranged" version = "0.5.8" @@ -445,10 +475,19 @@ version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer", - "const-oid", - "crypto-common", - "subtle", + "block-buffer 0.10.4", + "crypto-common 0.1.7", +] + +[[package]] +name = "digest" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" +dependencies = [ + "block-buffer 0.12.0", + "crypto-common 0.2.2", + "ctutils", ] [[package]] @@ -512,24 +551,23 @@ dependencies = [ [[package]] name = "etcetera" -version = "0.8.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" +checksum = "26c7b13d0780cb82722fd59f6f57f925e143427e4a75313a6c77243bf5326ae6" dependencies = [ "cfg-if", "home", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] name = "etcetera" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c7b13d0780cb82722fd59f6f57f925e143427e4a75313a6c77243bf5326ae6" +checksum = "de48cc4d1c1d97a20fd819def54b890cadde72ed3ad0c614822a0a433361be96" dependencies = [ "cfg-if", - "home", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -568,9 +606,9 @@ checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" [[package]] name = "flume" -version = "0.11.1" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" +checksum = "5e139bc46ca777eb5efaf62df0ab8cc5fd400866427e56c68b22e414e53bd3be" dependencies = [ "futures-core", "futures-sink", @@ -589,6 +627,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "form_urlencoded" version = "1.2.2" @@ -739,6 +783,7 @@ dependencies = [ "cfg-if", "libc", "r-efi 6.0.0", + "rand_core 0.10.1", "wasip2", "wasip3", ] @@ -773,10 +818,19 @@ name = "hashbrown" version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash 0.1.5", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ "allocator-api2", "equivalent", - "foldhash", + "foldhash 0.2.0", ] [[package]] @@ -787,11 +841,11 @@ checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" [[package]] name = "hashlink" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" +checksum = "ea0b22561a9c04a7cb1a302c013e0259cd3b4bb619f145b32f72b8b4bcbed230" dependencies = [ - "hashbrown 0.15.5", + "hashbrown 0.16.1", ] [[package]] @@ -808,20 +862,20 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hkdf" -version = "0.12.4" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +checksum = "4aaa26c720c68b866f2c96ef5c1264b3e6f473fe5d4ce61cd44bbe913e553018" dependencies = [ "hmac", ] [[package]] name = "hmac" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f" dependencies = [ - "digest", + "digest 0.11.3", ] [[package]] @@ -878,6 +932,15 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "hybrid-array" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da" +dependencies = [ + "typenum", +] + [[package]] name = "hyper" version = "1.9.0" @@ -1191,9 +1254,6 @@ name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -dependencies = [ - "spin", -] [[package]] name = "leb128fmt" @@ -1207,12 +1267,6 @@ version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" -[[package]] -name = "libm" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" - [[package]] name = "libredox" version = "0.1.16" @@ -1280,12 +1334,12 @@ checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" [[package]] name = "md-5" -version = "0.10.6" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +checksum = "69b6441f590336821bb897fb28fc622898ccceb1d6cea3fde5ea86b090c4de98" dependencies = [ "cfg-if", - "digest", + "digest 0.11.3", ] [[package]] @@ -1344,22 +1398,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-bigint-dig" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7" -dependencies = [ - "lazy_static", - "libm", - "num-integer", - "num-iter", - "num-traits", - "rand 0.8.6", - "smallvec", - "zeroize", -] - [[package]] name = "num-complex" version = "0.4.6" @@ -1413,7 +1451,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", - "libm", ] [[package]] @@ -1600,15 +1637,6 @@ dependencies = [ "syn", ] -[[package]] -name = "pem-rfc7468" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" -dependencies = [ - "base64ct", -] - [[package]] name = "percent-encoding" version = "2.3.2" @@ -1641,27 +1669,6 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" -[[package]] -name = "pkcs1" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" -dependencies = [ - "der", - "pkcs8", - "spki", -] - -[[package]] -name = "pkcs8" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" -dependencies = [ - "der", - "spki", -] - [[package]] name = "pkg-config" version = "0.3.33" @@ -1799,35 +1806,25 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" -[[package]] -name = "rand" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" -dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - [[package]] name = "rand" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" dependencies = [ - "rand_chacha 0.9.0", + "rand_chacha", "rand_core 0.9.5", ] [[package]] -name = "rand_chacha" -version = "0.3.1" +name = "rand" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", + "chacha20", + "getrandom 0.4.2", + "rand_core 0.10.1", ] [[package]] @@ -1842,21 +1839,18 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" dependencies = [ - "getrandom 0.2.17", + "getrandom 0.3.4", ] [[package]] name = "rand_core" -version = "0.9.5" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" -dependencies = [ - "getrandom 0.3.4", -] +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" [[package]] name = "redox_syscall" @@ -1973,26 +1967,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "rsa" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d" -dependencies = [ - "const-oid", - "digest", - "num-bigint-dig", - "num-integer", - "num-traits", - "pkcs1", - "pkcs8", - "rand_core 0.6.4", - "signature", - "spki", - "subtle", - "zeroize", -] - [[package]] name = "rustc-hash" version = "2.1.2" @@ -2288,13 +2262,13 @@ dependencies = [ [[package]] name = "sha1" -version = "0.10.6" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +checksum = "aacc4cc499359472b4abe1bf11d0b12e688af9a805fa5e3016f9a386dc2d0214" dependencies = [ "cfg-if", - "cpufeatures", - "digest", + "cpufeatures 0.3.0", + "digest 0.11.3", ] [[package]] @@ -2304,8 +2278,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", - "cpufeatures", - "digest", + "cpufeatures 0.2.17", + "digest 0.10.7", +] + +[[package]] +name = "sha2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "digest 0.11.3", ] [[package]] @@ -2323,16 +2308,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" -[[package]] -name = "signature" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" -dependencies = [ - "digest", - "rand_core 0.6.4", -] - [[package]] name = "slab" version = "0.4.12" @@ -2367,21 +2342,11 @@ dependencies = [ "lock_api", ] -[[package]] -name = "spki" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" -dependencies = [ - "base64ct", - "der", -] - [[package]] name = "sqlx" -version = "0.8.6" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fefb893899429669dcdd979aff487bd78f4064e5e7907e4269081e0ef7d97dc" +checksum = "378620ccc25c62c89d8be1c819e76a88d59bdcc3304733330788948e619bfd71" dependencies = [ "sqlx-core", "sqlx-macros", @@ -2392,12 +2357,13 @@ dependencies = [ [[package]] name = "sqlx-core" -version = "0.8.6" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee6798b1838b6a0f69c007c133b8df5866302197e404e8b6ee8ed3e3a5e68dc6" +checksum = "05b44e85bf579a8eeb4ceaa77a3a523baf2bf0e9bac7e40f405d537b5d2d5ccb" dependencies = [ "base64 0.22.1", "bytes", + "cfg-if", "crc", "crossbeam-queue", "either", @@ -2406,16 +2372,15 @@ dependencies = [ "futures-intrusive", "futures-io", "futures-util", - "hashbrown 0.15.5", + "hashbrown 0.16.1", "hashlink", "indexmap 2.14.0", "log", "memchr", - "once_cell", "percent-encoding", "serde", "serde_json", - "sha2", + "sha2 0.10.9", "smallvec", "thiserror", "tokio", @@ -2426,9 +2391,9 @@ dependencies = [ [[package]] name = "sqlx-macros" -version = "0.8.6" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2d452988ccaacfbf5e0bdbc348fb91d7c8af5bee192173ac3636b5fb6e6715d" +checksum = "bd2b84f2bc39a5705ef27ec785a11c934a41bbd4a24941e257927cddc26b60bf" dependencies = [ "proc-macro2", "quote", @@ -2439,76 +2404,61 @@ dependencies = [ [[package]] name = "sqlx-macros-core" -version = "0.8.6" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19a9c1841124ac5a61741f96e1d9e2ec77424bf323962dd894bdb93f37d5219b" +checksum = "fb8d96de5fdc85a5c4ec813432b523ec637e80ba98f046555f75f7908ddac7c3" dependencies = [ + "cfg-if", "dotenvy", "either", "heck", "hex", - "once_cell", "proc-macro2", "quote", "serde", "serde_json", - "sha2", + "sha2 0.10.9", "sqlx-core", "sqlx-mysql", "sqlx-postgres", "sqlx-sqlite", "syn", + "thiserror", "tokio", "url", ] [[package]] name = "sqlx-mysql" -version = "0.8.6" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526" +checksum = "90b8020fe17c5f2c245bfa2505d7ef59c5604839527c740266ad2214acebea27" dependencies = [ - "atoi", - "base64 0.22.1", "bitflags", "byteorder", "bytes", "crc", - "digest", + "digest 0.11.3", "dotenvy", "either", - "futures-channel", "futures-core", - "futures-io", "futures-util", "generic-array", - "hex", - "hkdf", - "hmac", - "itoa", "log", - "md-5", - "memchr", - "once_cell", "percent-encoding", - "rand 0.8.6", - "rsa", "serde", "sha1", - "sha2", - "smallvec", + "sha2 0.11.0", "sqlx-core", - "stringprep", "thiserror", "tracing", - "whoami", ] [[package]] name = "sqlx-postgres" -version = "0.8.6" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46" +checksum = "87a2bdd6e83f6b3ea525ca9fee568030508b58355a43d0b2c1674d5f79dcd65e" dependencies = [ "atoi", "base64 0.22.1", @@ -2516,23 +2466,21 @@ dependencies = [ "byteorder", "crc", "dotenvy", - "etcetera 0.8.0", + "etcetera 0.11.0", "futures-channel", "futures-core", "futures-util", "hex", "hkdf", "hmac", - "home", "itoa", "log", "md-5", "memchr", - "once_cell", - "rand 0.8.6", + "rand 0.10.1", "serde", "serde_json", - "sha2", + "sha2 0.11.0", "smallvec", "sqlx-core", "stringprep", @@ -2543,12 +2491,13 @@ dependencies = [ [[package]] name = "sqlx-sqlite" -version = "0.8.6" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2d12fe70b2c1b4401038055f90f151b78208de1f9f89a7dbfd41587a10c3eea" +checksum = "488e99c397a62007e4229aec669a179816339afc6d2620ca6fa420dbee2e982c" dependencies = [ "atoi", "flume", + "form_urlencoded", "futures-channel", "futures-core", "futures-executor", @@ -2558,7 +2507,6 @@ dependencies = [ "log", "percent-encoding", "serde", - "serde_urlencoded", "sqlx-core", "thiserror", "tracing", @@ -3211,12 +3159,6 @@ dependencies = [ "wit-bindgen 0.51.0", ] -[[package]] -name = "wasite" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" - [[package]] name = "wasm-bindgen" version = "0.2.118" @@ -3328,13 +3270,9 @@ dependencies = [ [[package]] name = "whoami" -version = "1.6.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d" -dependencies = [ - "libredox", - "wasite", -] +checksum = "998767ef88740d1f5b0682a9c53c24431453923962269c2db68ee43788c5a40d" [[package]] name = "winapi" @@ -3417,22 +3355,13 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -3441,7 +3370,7 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -3453,67 +3382,34 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - [[package]] name = "windows-targets" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -3526,48 +3422,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" diff --git a/Cargo.toml b/Cargo.toml index d87fe08..911a9f1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,13 +13,14 @@ keywords = ["sqlx", "tracing", "opentelemetry", "database", "observability"] categories = ["database", "development-tools::debugging", "development-tools::profiling", "asynchronous"] [features] +offline = ["sqlx/macros"] postgres = ["sqlx/postgres"] sqlite = ["sqlx/sqlite"] mysql = ["sqlx/mysql"] [dependencies] futures = { version = "0.3" } -sqlx = { version = "0.8", default-features = false, features = ["derive"] } +sqlx = { version = "0.9", default-features = false, features = ["derive"] } tracing = { version = "0.1" } [dev-dependencies] @@ -29,6 +30,6 @@ opentelemetry-testing = "0.1" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" serial_test = { version = "3.4" } -sqlx = { version = "0.8", features = ["runtime-tokio"] } +sqlx = { version = "0.9", features = ["runtime-tokio"] } testcontainers = "0.25" tokio = { version = "1", features = ["macros", "rt-multi-thread"] } diff --git a/src/connection.rs b/src/connection.rs index ce9ea7c..ad50225 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -18,15 +18,16 @@ where type Database = DB; #[doc(hidden)] - fn describe<'e, 'q: 'e>( + #[cfg(feature = "offline")] + fn describe<'e>( self, - sql: &'q str, + sql: sqlx::SqlStr, ) -> futures::future::BoxFuture<'e, Result, sqlx::Error>> where 'c: 'e, { let attrs = &self.attributes; - let span = crate::instrument!("sqlx.describe", sql, attrs); + let span = crate::span::span_for_sql::("sqlx.describe", sql.as_ref(), attrs); let fut = self.inner.as_mut().describe(sql); Box::pin(async move { fut.await.inspect_err(crate::span::record_error) }.instrument(span)) } @@ -42,9 +43,11 @@ where E: 'q + sqlx::Execute<'q, Self::Database>, 'c: 'e, { - let sql = query.sql(); let attrs = &self.attributes; - let span = crate::instrument!("sqlx.execute", sql, attrs); + let (query, span) = match crate::instrument!("sqlx.execute", query, attrs) { + Ok(v) => v, + Err(e) => return Box::pin(async move { Err(e) }), + }; let fut = self.inner.execute(query); Box::pin(async move { fut.await.inspect_err(crate::span::record_error) }.instrument(span)) } @@ -60,11 +63,12 @@ where E: 'q + sqlx::Execute<'q, Self::Database>, 'c: 'e, { - let sql = query.sql(); let attrs = &self.attributes; - let span = crate::instrument!("sqlx.execute_many", sql, attrs); + let (query, span) = match crate::instrument!("sqlx.execute_many", query, attrs) { + Ok(v) => v, + Err(e) => return Box::pin(futures::stream::once(futures::future::ready(Err(e)))), + }; let stream = self.inner.execute_many(query); - use futures::StreamExt; Box::pin( stream .inspect(move |_| { @@ -82,11 +86,12 @@ where E: 'q + sqlx::Execute<'q, Self::Database>, 'c: 'e, { - let sql = query.sql(); let attrs = &self.attributes; - let span = crate::instrument!("sqlx.fetch", sql, attrs); + let (query, span) = match crate::instrument!("sqlx.fetch", query, attrs) { + Ok(v) => v, + Err(e) => return Box::pin(futures::stream::once(futures::future::ready(Err(e)))), + }; let stream = self.inner.fetch(query); - use futures::StreamExt; Box::pin( stream .inspect(move |_| { @@ -107,9 +112,11 @@ where E: 'q + sqlx::Execute<'q, Self::Database>, 'c: 'e, { - let sql = query.sql(); let attrs = &self.attributes; - let span = crate::instrument!("sqlx.fetch_all", sql, attrs); + let (query, span) = match crate::instrument!("sqlx.fetch_all", query, attrs) { + Ok(v) => v, + Err(e) => return Box::pin(async move { Err(e) }), + }; let fut = self.inner.fetch_all(query); Box::pin( async move { @@ -141,9 +148,11 @@ where E: 'q + sqlx::Execute<'q, Self::Database>, 'c: 'e, { - let sql = query.sql(); let attrs = &self.attributes; - let span = crate::instrument!("sqlx.fetch_all", sql, attrs); + let (query, span) = match crate::instrument!("sqlx.fetch_all", query, attrs) { + Ok(v) => v, + Err(e) => return Box::pin(futures::stream::once(futures::future::ready(Err(e)))), + }; let stream = self.inner.fetch_many(query); Box::pin( stream @@ -162,9 +171,11 @@ where E: 'q + sqlx::Execute<'q, Self::Database>, 'c: 'e, { - let sql = query.sql(); let attrs = &self.attributes; - let span = crate::instrument!("sqlx.fetch_one", sql, attrs); + let (query, span) = match crate::instrument!("sqlx.fetch_one", query, attrs) { + Ok(v) => v, + Err(e) => return Box::pin(async move { Err(e) }), + }; let fut = self.inner.fetch_one(query); Box::pin( async move { @@ -189,9 +200,11 @@ where E: 'q + sqlx::Execute<'q, Self::Database>, 'c: 'e, { - let sql = query.sql(); let attrs = &self.attributes; - let span = crate::instrument!("sqlx.fetch_optional", sql, attrs); + let (query, span) = match crate::instrument!("sqlx.fetch_optional", query, attrs) { + Ok(v) => v, + Err(e) => return Box::pin(async move { Err(e) }), + }; let fut = self.inner.fetch_optional(query); Box::pin( async move { @@ -208,35 +221,35 @@ where ) } - fn prepare<'e, 'q: 'e>( + fn prepare<'e>( self, - query: &'q str, + query: sqlx::SqlStr, ) -> futures::future::BoxFuture< 'e, - Result<::Statement<'q>, sqlx::Error>, + Result<::Statement, sqlx::Error>, > where 'c: 'e, { let attrs = &self.attributes; - let span = crate::instrument!("sqlx.prepare", query, attrs); + let span = crate::span::span_for_sql::("sqlx.prepare", query.as_ref(), attrs); let fut = self.inner.prepare(query); Box::pin(async move { fut.await.inspect_err(crate::span::record_error) }.instrument(span)) } - fn prepare_with<'e, 'q: 'e>( + fn prepare_with<'e>( self, - sql: &'q str, + sql: sqlx::SqlStr, parameters: &'e [::TypeInfo], ) -> futures::future::BoxFuture< 'e, - Result<::Statement<'q>, sqlx::Error>, + Result<::Statement, sqlx::Error>, > where 'c: 'e, { let attrs = &self.attributes; - let span = crate::instrument!("sqlx.prepare_with", sql, attrs); + let span = crate::span::span_for_sql::("sqlx.prepare_with", sql.as_ref(), attrs); let fut = self.inner.prepare_with(sql, parameters); Box::pin(async move { fut.await.inspect_err(crate::span::record_error) }.instrument(span)) } @@ -250,15 +263,16 @@ where type Database = DB; #[doc(hidden)] - fn describe<'e, 'q: 'e>( + #[cfg(feature = "offline")] + fn describe<'e>( self, - sql: &'q str, + sql: sqlx::SqlStr, ) -> futures::future::BoxFuture<'e, Result, sqlx::Error>> where 'c: 'e, { let attrs = &self.attributes; - let span = crate::instrument!("sqlx.describe", sql, attrs); + let span = crate::span::span_for_sql::("sqlx.describe", sql.as_ref(), attrs); let fut = self.inner.describe(sql); Box::pin(async move { fut.await.inspect_err(crate::span::record_error) }.instrument(span)) } @@ -274,9 +288,11 @@ where E: 'q + sqlx::Execute<'q, Self::Database>, 'c: 'e, { - let sql = query.sql(); let attrs = &self.attributes; - let span = crate::instrument!("sqlx.execute", sql, attrs); + let (query, span) = match crate::instrument!("sqlx.execute", query, attrs) { + Ok(v) => v, + Err(e) => return Box::pin(async move { Err(e) }), + }; let fut = self.inner.execute(query); Box::pin(async move { fut.await.inspect_err(crate::span::record_error) }.instrument(span)) } @@ -292,11 +308,12 @@ where E: 'q + sqlx::Execute<'q, Self::Database>, 'c: 'e, { - let sql = query.sql(); let attrs = &self.attributes; - let span = crate::instrument!("sqlx.execute_many", sql, attrs); + let (query, span) = match crate::instrument!("sqlx.execute_many", query, attrs) { + Ok(v) => v, + Err(e) => return Box::pin(futures::stream::once(futures::future::ready(Err(e)))), + }; let stream = self.inner.execute_many(query); - use futures::StreamExt; Box::pin( stream .inspect(move |_| { @@ -314,11 +331,12 @@ where E: 'q + sqlx::Execute<'q, Self::Database>, 'c: 'e, { - let sql = query.sql(); let attrs = &self.attributes; - let span = crate::instrument!("sqlx.fetch", sql, attrs); + let (query, span) = match crate::instrument!("sqlx.fetch", query, attrs) { + Ok(v) => v, + Err(e) => return Box::pin(futures::stream::once(futures::future::ready(Err(e)))), + }; let stream = self.inner.fetch(query); - use futures::StreamExt; Box::pin( stream .inspect(move |_| { @@ -339,9 +357,11 @@ where E: 'q + sqlx::Execute<'q, Self::Database>, 'c: 'e, { - let sql = query.sql(); let attrs = &self.attributes; - let span = crate::instrument!("sqlx.fetch_all", sql, attrs); + let (query, span) = match crate::instrument!("sqlx.fetch_all", query, attrs) { + Ok(v) => v, + Err(e) => return Box::pin(async move { Err(e) }), + }; let fut = self.inner.fetch_all(query); Box::pin( async move { @@ -373,9 +393,11 @@ where E: 'q + sqlx::Execute<'q, Self::Database>, 'c: 'e, { - let sql = query.sql(); let attrs = &self.attributes; - let span = crate::instrument!("sqlx.fetch_all", sql, attrs); + let (query, span) = match crate::instrument!("sqlx.fetch_all", query, attrs) { + Ok(v) => v, + Err(e) => return Box::pin(futures::stream::once(futures::future::ready(Err(e)))), + }; let stream = self.inner.fetch_many(query); Box::pin( stream @@ -394,9 +416,11 @@ where E: 'q + sqlx::Execute<'q, Self::Database>, 'c: 'e, { - let sql = query.sql(); let attrs = &self.attributes; - let span = crate::instrument!("sqlx.fetch_one", sql, attrs); + let (query, span) = match crate::instrument!("sqlx.fetch_one", query, attrs) { + Ok(v) => v, + Err(e) => return Box::pin(async move { Err(e) }), + }; let fut = self.inner.fetch_one(query); Box::pin( async move { @@ -419,9 +443,11 @@ where E: 'q + sqlx::Execute<'q, Self::Database>, 'c: 'e, { - let sql = query.sql(); let attrs = &self.attributes; - let span = crate::instrument!("sqlx.fetch_optional", sql, attrs); + let (query, span) = match crate::instrument!("sqlx.fetch_optional", query, attrs) { + Ok(v) => v, + Err(e) => return Box::pin(async move { Err(e) }), + }; let fut = self.inner.fetch_optional(query); Box::pin( async move { @@ -433,35 +459,35 @@ where ) } - fn prepare<'e, 'q: 'e>( + fn prepare<'e>( self, - query: &'q str, + query: sqlx::SqlStr, ) -> futures::future::BoxFuture< 'e, - Result<::Statement<'q>, sqlx::Error>, + Result<::Statement, sqlx::Error>, > where 'c: 'e, { let attrs = &self.attributes; - let span = crate::instrument!("sqlx.prepare", query, attrs); + let span = crate::span::span_for_sql::("sqlx.prepare", query.as_ref(), attrs); let fut = self.inner.prepare(query); Box::pin(async move { fut.await.inspect_err(crate::span::record_error) }.instrument(span)) } - fn prepare_with<'e, 'q: 'e>( + fn prepare_with<'e>( self, - sql: &'q str, + sql: sqlx::SqlStr, parameters: &'e [::TypeInfo], ) -> futures::future::BoxFuture< 'e, - Result<::Statement<'q>, sqlx::Error>, + Result<::Statement, sqlx::Error>, > where 'c: 'e, { let attrs = &self.attributes; - let span = crate::instrument!("sqlx.prepare_with", sql, attrs); + let span = crate::span::span_for_sql::("sqlx.prepare_with", sql.as_ref(), attrs); let fut = self.inner.prepare_with(sql, parameters); Box::pin(async move { fut.await.inspect_err(crate::span::record_error) }.instrument(span)) } diff --git a/src/pool.rs b/src/pool.rs index a0cbce9..7049b94 100644 --- a/src/pool.rs +++ b/src/pool.rs @@ -9,12 +9,16 @@ where type Database = DB; #[doc(hidden)] - fn describe<'e, 'q: 'e>( + #[cfg(feature = "offline")] + fn describe<'e>( self, - sql: &'q str, - ) -> futures::future::BoxFuture<'e, Result, sqlx::Error>> { + sql: sqlx::SqlStr, + ) -> futures::future::BoxFuture<'e, Result, sqlx::Error>> + where + 'p: 'e, + { let attrs = &self.attributes; - let span = crate::instrument!("sqlx.describe", sql, attrs); + let span = crate::span::span_for_sql::("sqlx.describe", sql.as_ref(), attrs); let fut = self.inner.describe(sql); Box::pin(async move { fut.await.inspect_err(crate::span::record_error) }.instrument(span)) } @@ -29,9 +33,11 @@ where where E: 'q + sqlx::Execute<'q, Self::Database>, { - let sql = query.sql(); let attrs = &self.attributes; - let span = crate::instrument!("sqlx.execute", sql, attrs); + let (query, span) = match crate::instrument!("sqlx.execute", query, attrs) { + Ok(v) => v, + Err(e) => return Box::pin(async move { Err(e) }), + }; let fut = self.inner.execute(query); Box::pin(async move { fut.await.inspect_err(crate::span::record_error) }.instrument(span)) } @@ -46,11 +52,12 @@ where where E: 'q + sqlx::Execute<'q, Self::Database>, { - let sql = query.sql(); let attrs = &self.attributes; - let span = crate::instrument!("sqlx.execute_many", sql, attrs); + let (query, span) = match crate::instrument!("sqlx.execute_many", query, attrs) { + Ok(v) => v, + Err(e) => return Box::pin(futures::stream::once(futures::future::ready(Err(e)))), + }; let stream = self.inner.execute_many(query); - use futures::StreamExt; Box::pin( stream .inspect(move |_| { @@ -67,11 +74,12 @@ where where E: 'q + sqlx::Execute<'q, Self::Database>, { - let sql = query.sql(); let attrs = &self.attributes; - let span = crate::instrument!("sqlx.fetch", sql, attrs); + let (query, span) = match crate::instrument!("sqlx.fetch", query, attrs) { + Ok(v) => v, + Err(e) => return Box::pin(futures::stream::once(futures::future::ready(Err(e)))), + }; let stream = self.inner.fetch(query); - use futures::StreamExt; Box::pin( stream .inspect(move |_| { @@ -91,9 +99,11 @@ where where E: 'q + sqlx::Execute<'q, Self::Database>, { - let sql = query.sql(); let attrs = &self.attributes; - let span = crate::instrument!("sqlx.fetch_all", sql, attrs); + let (query, span) = match crate::instrument!("sqlx.fetch_all", query, attrs) { + Ok(v) => v, + Err(e) => return Box::pin(async move { Err(e) }), + }; let fut = self.inner.fetch_all(query); Box::pin( async move { @@ -124,9 +134,11 @@ where where E: 'q + sqlx::Execute<'q, Self::Database>, { - let sql = query.sql(); let attrs = &self.attributes; - let span = crate::instrument!("sqlx.fetch_all", sql, attrs); + let (query, span) = match crate::instrument!("sqlx.fetch_all", query, attrs) { + Ok(v) => v, + Err(e) => return Box::pin(futures::stream::once(futures::future::ready(Err(e)))), + }; let stream = self.inner.fetch_many(query); Box::pin( stream @@ -144,9 +156,11 @@ where where E: 'q + sqlx::Execute<'q, Self::Database>, { - let sql = query.sql(); let attrs = &self.attributes; - let span = crate::instrument!("sqlx.fetch_one", sql, attrs); + let (query, span) = match crate::instrument!("sqlx.fetch_one", query, attrs) { + Ok(v) => v, + Err(e) => return Box::pin(async move { Err(e) }), + }; let fut = self.inner.fetch_one(query); Box::pin( async move { @@ -168,9 +182,11 @@ where where E: 'q + sqlx::Execute<'q, Self::Database>, { - let sql = query.sql(); let attrs = &self.attributes; - let span = crate::instrument!("sqlx.fetch_optional", sql, attrs); + let (query, span) = match crate::instrument!("sqlx.fetch_optional", query, attrs) { + Ok(v) => v, + Err(e) => return Box::pin(async move { Err(e) }), + }; let fut = self.inner.fetch_optional(query); Box::pin( async move { @@ -182,29 +198,32 @@ where ) } - fn prepare<'e, 'q: 'e>( + fn prepare<'e>( self, - query: &'q str, + query: sqlx::SqlStr, ) -> futures::future::BoxFuture< 'e, - Result<::Statement<'q>, sqlx::Error>, + Result<::Statement, sqlx::Error>, > { let attrs = &self.attributes; - let span = crate::instrument!("sqlx.prepare", query, attrs); + let span = crate::span::span_for_sql::("sqlx.prepare", query.as_ref(), attrs); let fut = self.inner.prepare(query); Box::pin(async move { fut.await.inspect_err(crate::span::record_error) }.instrument(span)) } - fn prepare_with<'e, 'q: 'e>( + fn prepare_with<'e>( self, - sql: &'q str, + sql: sqlx::SqlStr, parameters: &'e [::TypeInfo], ) -> futures::future::BoxFuture< 'e, - Result<::Statement<'q>, sqlx::Error>, - > { + Result<::Statement, sqlx::Error>, + > + where + 'p: 'e, + { let attrs = &self.attributes; - let span = crate::instrument!("sqlx.prepare_with", sql, attrs); + let span = crate::span::span_for_sql::("sqlx.prepare_with", sql.as_ref(), attrs); let fut = self.inner.prepare_with(sql, parameters); Box::pin(async move { fut.await.inspect_err(crate::span::record_error) }.instrument(span)) } diff --git a/src/span.rs b/src/span.rs index af42bce..8112923 100644 --- a/src/span.rs +++ b/src/span.rs @@ -1,45 +1,98 @@ -/// Macro to create a tracing span for a SQLx operation with OpenTelemetry-compatible fields. +use sqlx::{Database, Execute}; + +use crate::Attributes; + +pub(crate) type Reconstructed = (sqlx::SqlStr, Option<::Arguments>); + +/// Extracts SQL for tracing, then rebuilds a query value for the inner executor. +/// +/// Required because sqlx 0.9's [`Execute::sql()`] consumes the query. +pub(crate) fn prepare_query<'q, DB, E>( + name: &'static str, + mut query: E, + attributes: &Attributes, +) -> Result<(Reconstructed, tracing::Span), sqlx::Error> +where + DB: Database + crate::prelude::Database, + E: Execute<'q, DB>, +{ + let arguments = query.take_arguments().map_err(sqlx::Error::Encode)?; + let sql = query.sql(); + let span = span_for_sql::(name, sql.as_ref(), attributes); + Ok(((sql, arguments), span)) +} + +/// Creates a tracing span for a SQL string without decomposing an [`Execute`] value. +pub(crate) fn span_for_sql( + name: &'static str, + statement: impl AsRef, + attributes: &Attributes, +) -> tracing::Span { + // Operation names must be string literals for tracing callsites. + macro_rules! span { + ($name:literal) => { + tracing::info_span!( + $name, + // Database name (if available) + "db.name" = attributes.database, + // Operation type (filled by SQLx or left empty) + "db.operation" = tracing::field::Empty, + // The SQL query text + "db.query.text" = statement.as_ref(), + // Number of affected rows (to be filled after execution) + "db.response.affected_rows" = tracing::field::Empty, + // Number of returned rows (to be filled after execution) + "db.response.returned_rows" = tracing::field::Empty, + // Status code of the response (to be filled after execution) + "db.response.status_code" = tracing::field::Empty, + // Table name (optional, left empty) + "db.sql.table" = tracing::field::Empty, + // Database system (e.g., "postgresql", "sqlite") + "db.system.name" = DB::SYSTEM, + // Error type, message, and stacktrace (to be filled on error) + "error.type" = tracing::field::Empty, + "error.message" = tracing::field::Empty, + "error.stacktrace" = tracing::field::Empty, + // Peer (server) host and port + "net.peer.name" = attributes.host, + "net.peer.port" = attributes.port, + // OpenTelemetry semantic fields + "otel.kind" = "client", + "otel.status_code" = tracing::field::Empty, + "otel.status_description" = tracing::field::Empty, + // Peer service name (if set) + "peer.service" = attributes.name, + ) + }; + } + + match name { + "sqlx.describe" => span!("sqlx.describe"), + "sqlx.execute" => span!("sqlx.execute"), + "sqlx.execute_many" => span!("sqlx.execute_many"), + "sqlx.fetch" => span!("sqlx.fetch"), + "sqlx.fetch_all" => span!("sqlx.fetch_all"), + "sqlx.fetch_one" => span!("sqlx.fetch_one"), + "sqlx.fetch_optional" => span!("sqlx.fetch_optional"), + "sqlx.prepare" => span!("sqlx.prepare"), + "sqlx.prepare_with" => span!("sqlx.prepare_with"), + _ => span!("sqlx.query"), + } +} + +/// Prepares a query for execution and returns the reconstructed query with its tracing span. +/// +/// Macro to instrument a SQLx operation with OpenTelemetry-compatible fields. /// -/// - `$name`: The operation name (e.g., "sqlx.execute"). -/// - `$statement`: The SQL statement being executed. +/// - `$name`: The operation name (e.g., `"sqlx.execute"`). +/// - `$query`: The query value implementing [`sqlx::Execute`]. /// - `$attributes`: Connection or pool attributes for peer and db context. /// /// This macro is used internally by the crate to instrument all major SQLx operations. #[macro_export] macro_rules! instrument { - ($name:expr, $statement:expr, $attributes:expr) => { - tracing::info_span!( - $name, - // Database name (if available) - "db.name" = $attributes.database, - // Operation type (filled by SQLx or left empty) - "db.operation" = ::tracing::field::Empty, - // The SQL query text - "db.query.text" = $statement, - // Number of affected rows (to be filled after execution) - "db.response.affected_rows" = ::tracing::field::Empty, - // Number of returned rows (to be filled after execution) - "db.response.returned_rows" = ::tracing::field::Empty, - // Status code of the response (to be filled after execution) - "db.response.status_code" = ::tracing::field::Empty, - // Table name (optional, left empty) - "db.sql.table" = ::tracing::field::Empty, - // Database system (e.g., "postgresql", "sqlite") - "db.system.name" = DB::SYSTEM, - // Error type, message, and stacktrace (to be filled on error) - "error.type" = ::tracing::field::Empty, - "error.message" = ::tracing::field::Empty, - "error.stacktrace" = ::tracing::field::Empty, - // Peer (server) host and port - "net.peer.name" = $attributes.host, - "net.peer.port" = $attributes.port, - // OpenTelemetry semantic fields - "otel.kind" = "client", - "otel.status_code" = ::tracing::field::Empty, - "otel.status_description" = ::tracing::field::Empty, - // Peer service name (if set) - "peer.service" = $attributes.name, - ) + ($name:expr, $query:expr, $attributes:expr) => { + $crate::span::prepare_query($name, $query, $attributes) }; } diff --git a/src/transaction.rs b/src/transaction.rs index 253f4c5..d99bc2b 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -40,18 +40,19 @@ where type Database = DB; #[doc(hidden)] - fn describe<'e, 'q: 'e>( + #[cfg(feature = "offline")] + fn describe<'e>( self, - sql: &'q str, + sql: sqlx::SqlStr, ) -> futures::future::BoxFuture<'e, Result, sqlx::Error>> where 'c: 'e, { let attrs = &self.attributes; - let span = crate::instrument!("sqlx.describe", sql, attrs); + let span = crate::span::span_for_sql::("sqlx.describe", sql.as_ref(), attrs); Box::pin( async move { - let fut = (&mut self.inner).describe(sql); + let fut = (&mut *self.inner).describe(sql); fut.await.inspect_err(crate::span::record_error) } .instrument(span), @@ -69,9 +70,11 @@ where E: 'q + sqlx::Execute<'q, Self::Database>, 'c: 'e, { - let sql = query.sql(); let attrs = &self.attributes; - let span = crate::instrument!("sqlx.execute", sql, attrs); + let (query, span) = match crate::instrument!("sqlx.execute", query, attrs) { + Ok(v) => v, + Err(e) => return Box::pin(async move { Err(e) }), + }; let fut = (&mut self.inner).execute(query); Box::pin(async move { fut.await.inspect_err(crate::span::record_error) }.instrument(span)) } @@ -87,11 +90,12 @@ where E: 'q + sqlx::Execute<'q, Self::Database>, 'c: 'e, { - let sql = query.sql(); let attrs = &self.attributes; - let span = crate::instrument!("sqlx.execute_many", sql, attrs); + let (query, span) = match crate::instrument!("sqlx.execute_many", query, attrs) { + Ok(v) => v, + Err(e) => return Box::pin(futures::stream::once(futures::future::ready(Err(e)))), + }; let stream = (&mut self.inner).execute_many(query); - use futures::StreamExt; Box::pin( stream .inspect(move |_| { @@ -109,11 +113,12 @@ where E: 'q + sqlx::Execute<'q, Self::Database>, 'c: 'e, { - let sql = query.sql(); let attrs = &self.attributes; - let span = crate::instrument!("sqlx.fetch", sql, attrs); + let (query, span) = match crate::instrument!("sqlx.fetch", query, attrs) { + Ok(v) => v, + Err(e) => return Box::pin(futures::stream::once(futures::future::ready(Err(e)))), + }; let stream = (&mut self.inner).fetch(query); - use futures::StreamExt; Box::pin( stream .inspect(move |_| { @@ -134,9 +139,11 @@ where E: 'q + sqlx::Execute<'q, Self::Database>, 'c: 'e, { - let sql = query.sql(); let attrs = &self.attributes; - let span = crate::instrument!("sqlx.fetch_all", sql, attrs); + let (query, span) = match crate::instrument!("sqlx.fetch_all", query, attrs) { + Ok(v) => v, + Err(e) => return Box::pin(async move { Err(e) }), + }; let fut = (&mut self.inner).fetch_all(query); Box::pin( async move { @@ -168,9 +175,11 @@ where E: 'q + sqlx::Execute<'q, Self::Database>, 'c: 'e, { - let sql = query.sql(); let attrs = &self.attributes; - let span = crate::instrument!("sqlx.fetch_all", sql, attrs); + let (query, span) = match crate::instrument!("sqlx.fetch_all", query, attrs) { + Ok(v) => v, + Err(e) => return Box::pin(futures::stream::once(futures::future::ready(Err(e)))), + }; let stream = (&mut self.inner).fetch_many(query); Box::pin( stream @@ -189,9 +198,11 @@ where E: 'q + sqlx::Execute<'q, Self::Database>, 'c: 'e, { - let sql = query.sql(); let attrs = &self.attributes; - let span = crate::instrument!("sqlx.fetch_one", sql, attrs); + let (query, span) = match crate::instrument!("sqlx.fetch_one", query, attrs) { + Ok(v) => v, + Err(e) => return Box::pin(async move { Err(e) }), + }; let fut = (&mut self.inner).fetch_one(query); Box::pin( async move { @@ -214,9 +225,11 @@ where E: 'q + sqlx::Execute<'q, Self::Database>, 'c: 'e, { - let sql = query.sql(); let attrs = &self.attributes; - let span = crate::instrument!("sqlx.fetch_optional", sql, attrs); + let (query, span) = match crate::instrument!("sqlx.fetch_optional", query, attrs) { + Ok(v) => v, + Err(e) => return Box::pin(async move { Err(e) }), + }; let fut = (&mut self.inner).fetch_optional(query); Box::pin( async move { @@ -228,35 +241,35 @@ where ) } - fn prepare<'e, 'q: 'e>( + fn prepare<'e>( self, - query: &'q str, + query: sqlx::SqlStr, ) -> futures::future::BoxFuture< 'e, - Result<::Statement<'q>, sqlx::Error>, + Result<::Statement, sqlx::Error>, > where 'c: 'e, { let attrs = &self.attributes; - let span = crate::instrument!("sqlx.prepare", query, attrs); + let span = crate::span::span_for_sql::("sqlx.prepare", query.as_ref(), attrs); let fut = (&mut self.inner).prepare(query); Box::pin(async move { fut.await.inspect_err(crate::span::record_error) }.instrument(span)) } - fn prepare_with<'e, 'q: 'e>( + fn prepare_with<'e>( self, - sql: &'q str, + sql: sqlx::SqlStr, parameters: &'e [::TypeInfo], ) -> futures::future::BoxFuture< 'e, - Result<::Statement<'q>, sqlx::Error>, + Result<::Statement, sqlx::Error>, > where 'c: 'e, { let attrs = &self.attributes; - let span = crate::instrument!("sqlx.prepare_with", sql, attrs); + let span = crate::span::span_for_sql::("sqlx.prepare_with", sql.as_ref(), attrs); let fut = (&mut self.inner).prepare_with(sql, parameters); Box::pin(async move { fut.await.inspect_err(crate::span::record_error) }.instrument(span)) } diff --git a/tests/common.rs b/tests/common.rs index a7d101f..672684d 100644 --- a/tests/common.rs +++ b/tests/common.rs @@ -11,7 +11,7 @@ pub async fn should_trace<'c, DB, E>( ) where DB: sqlx::Database, E: sqlx::Executor<'c, Database = DB>, - for<'q> DB::Arguments<'q>: 'q + sqlx::IntoArguments<'q, DB>, + DB::Arguments: sqlx::IntoArguments, (i32,): Send + Unpin + for<'r> sqlx::FromRow<'r, DB::Row>, { let scope = format!("should_{name}_{system}");