From fcbfcd14b633a527ff0d5588a4d76799c2fad115 Mon Sep 17 00:00:00 2001 From: Han Xu Date: Sun, 21 Jun 2026 16:31:51 +0000 Subject: [PATCH] remove duckdb dependency --- Cargo.lock | 739 ++---------------- Cargo.toml | 1 - crates/garmin-cli/Cargo.toml | 1 - crates/garmin-cli/src/cli/commands/devices.rs | 136 ++-- crates/garmin-cli/src/storage/parquet.rs | 58 +- 5 files changed, 175 insertions(+), 760 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6b905c0..1762ce3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,23 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "adler2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" - -[[package]] -name = "ahash" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" -dependencies = [ - "getrandom 0.2.16", - "once_cell", - "version_check", -] - [[package]] name = "ahash" version = "0.8.12" @@ -116,55 +99,22 @@ dependencies = [ "num-traits", ] -[[package]] -name = "arbitrary" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" -dependencies = [ - "derive_arbitrary", -] - -[[package]] -name = "arrayvec" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" - [[package]] name = "arrow" version = "54.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5ec52ba94edeed950e4a41f75d35376df196e8cb04437f7280a5aa49f20f796" dependencies = [ - "arrow-arith 54.3.1", - "arrow-array 54.3.1", - "arrow-buffer 54.3.1", - "arrow-cast 54.3.1", - "arrow-data 54.3.1", - "arrow-ord 54.3.1", - "arrow-row 54.3.1", - "arrow-schema 54.3.1", - "arrow-select 54.3.1", - "arrow-string 54.3.1", -] - -[[package]] -name = "arrow" -version = "56.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c26b57282a08ae92f727497805122fec964c6245cfa0e13f0e75452eaf3bc41f" -dependencies = [ - "arrow-arith 56.2.0", - "arrow-array 56.2.0", - "arrow-buffer 56.2.0", - "arrow-cast 56.1.0", - "arrow-data 56.2.0", - "arrow-ord 56.2.0", - "arrow-row 56.2.0", - "arrow-schema 56.2.0", - "arrow-select 56.2.0", - "arrow-string 56.2.0", + "arrow-arith", + "arrow-array", + "arrow-buffer", + "arrow-cast", + "arrow-data", + "arrow-ord", + "arrow-row", + "arrow-schema", + "arrow-select", + "arrow-string", ] [[package]] @@ -173,24 +123,10 @@ version = "54.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fc766fdacaf804cb10c7c70580254fcdb5d55cdfda2bc57b02baf5223a3af9e" dependencies = [ - "arrow-array 54.3.1", - "arrow-buffer 54.3.1", - "arrow-data 54.3.1", - "arrow-schema 54.3.1", - "chrono", - "num", -] - -[[package]] -name = "arrow-arith" -version = "56.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad08897b81588f60ba983e3ca39bda2b179bdd84dced378e7df81a5313802ef8" -dependencies = [ - "arrow-array 56.2.0", - "arrow-buffer 56.2.0", - "arrow-data 56.2.0", - "arrow-schema 56.2.0", + "arrow-array", + "arrow-buffer", + "arrow-data", + "arrow-schema", "chrono", "num", ] @@ -201,32 +137,16 @@ version = "54.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a12fcdb3f1d03f69d3ec26ac67645a8fe3f878d77b5ebb0b15d64a116c212985" dependencies = [ - "ahash 0.8.12", - "arrow-buffer 54.3.1", - "arrow-data 54.3.1", - "arrow-schema 54.3.1", + "ahash", + "arrow-buffer", + "arrow-data", + "arrow-schema", "chrono", "half", "hashbrown 0.15.5", "num", ] -[[package]] -name = "arrow-array" -version = "56.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8548ca7c070d8db9ce7aa43f37393e4bfcf3f2d3681df278490772fd1673d08d" -dependencies = [ - "ahash 0.8.12", - "arrow-buffer 56.2.0", - "arrow-data 56.2.0", - "arrow-schema 56.2.0", - "chrono", - "half", - "hashbrown 0.16.1", - "num", -] - [[package]] name = "arrow-buffer" version = "54.3.1" @@ -238,49 +158,17 @@ dependencies = [ "num", ] -[[package]] -name = "arrow-buffer" -version = "56.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e003216336f70446457e280807a73899dd822feaf02087d31febca1363e2fccc" -dependencies = [ - "bytes", - "half", - "num", -] - [[package]] name = "arrow-cast" version = "54.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ede6175fbc039dfc946a61c1b6d42fd682fcecf5ab5d148fbe7667705798cac9" dependencies = [ - "arrow-array 54.3.1", - "arrow-buffer 54.3.1", - "arrow-data 54.3.1", - "arrow-schema 54.3.1", - "arrow-select 54.3.1", - "atoi", - "base64", - "chrono", - "comfy-table", - "half", - "lexical-core", - "num", - "ryu", -] - -[[package]] -name = "arrow-cast" -version = "56.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eed61d9d73eda8df9e3014843def37af3050b5080a9acbe108f045a316d5a0be" -dependencies = [ - "arrow-array 56.2.0", - "arrow-buffer 56.2.0", - "arrow-data 56.2.0", - "arrow-schema 56.2.0", - "arrow-select 56.2.0", + "arrow-array", + "arrow-buffer", + "arrow-data", + "arrow-schema", + "arrow-select", "atoi", "base64", "chrono", @@ -297,20 +185,8 @@ version = "54.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61cfdd7d99b4ff618f167e548b2411e5dd2c98c0ddebedd7df433d34c20a4429" dependencies = [ - "arrow-buffer 54.3.1", - "arrow-schema 54.3.1", - "half", - "num", -] - -[[package]] -name = "arrow-data" -version = "56.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5c64fff1d142f833d78897a772f2e5b55b36cb3e6320376f0961ab0db7bd6d0" -dependencies = [ - "arrow-buffer 56.2.0", - "arrow-schema 56.2.0", + "arrow-buffer", + "arrow-schema", "half", "num", ] @@ -321,10 +197,10 @@ version = "54.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62ff528658b521e33905334723b795ee56b393dbe9cf76c8b1f64b648c65a60c" dependencies = [ - "arrow-array 54.3.1", - "arrow-buffer 54.3.1", - "arrow-data 54.3.1", - "arrow-schema 54.3.1", + "arrow-array", + "arrow-buffer", + "arrow-data", + "arrow-schema", "flatbuffers", ] @@ -334,24 +210,11 @@ version = "54.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0a3334a743bd2a1479dbc635540617a3923b4b2f6870f37357339e6b5363c21" dependencies = [ - "arrow-array 54.3.1", - "arrow-buffer 54.3.1", - "arrow-data 54.3.1", - "arrow-schema 54.3.1", - "arrow-select 54.3.1", -] - -[[package]] -name = "arrow-ord" -version = "56.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c8f82583eb4f8d84d4ee55fd1cb306720cddead7596edce95b50ee418edf66f" -dependencies = [ - "arrow-array 56.2.0", - "arrow-buffer 56.2.0", - "arrow-data 56.2.0", - "arrow-schema 56.2.0", - "arrow-select 56.2.0", + "arrow-array", + "arrow-buffer", + "arrow-data", + "arrow-schema", + "arrow-select", ] [[package]] @@ -360,23 +223,10 @@ version = "54.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d1d7a7291d2c5107e92140f75257a99343956871f3d3ab33a7b41532f79cb68" dependencies = [ - "arrow-array 54.3.1", - "arrow-buffer 54.3.1", - "arrow-data 54.3.1", - "arrow-schema 54.3.1", - "half", -] - -[[package]] -name = "arrow-row" -version = "56.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d07ba24522229d9085031df6b94605e0f4b26e099fb7cdeec37abd941a73753" -dependencies = [ - "arrow-array 56.2.0", - "arrow-buffer 56.2.0", - "arrow-data 56.2.0", - "arrow-schema 56.2.0", + "arrow-array", + "arrow-buffer", + "arrow-data", + "arrow-schema", "half", ] @@ -386,40 +236,17 @@ version = "54.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cfaf5e440be44db5413b75b72c2a87c1f8f0627117d110264048f2969b99e9" -[[package]] -name = "arrow-schema" -version = "56.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3aa9e59c611ebc291c28582077ef25c97f1975383f1479b12f3b9ffee2ffabe" -dependencies = [ - "bitflags 2.10.0", -] - [[package]] name = "arrow-select" version = "54.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69efcd706420e52cd44f5c4358d279801993846d1c2a8e52111853d61d55a619" dependencies = [ - "ahash 0.8.12", - "arrow-array 54.3.1", - "arrow-buffer 54.3.1", - "arrow-data 54.3.1", - "arrow-schema 54.3.1", - "num", -] - -[[package]] -name = "arrow-select" -version = "56.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c41dbbd1e97bfcaee4fcb30e29105fb2c75e4d82ae4de70b792a5d3f66b2e7a" -dependencies = [ - "ahash 0.8.12", - "arrow-array 56.2.0", - "arrow-buffer 56.2.0", - "arrow-data 56.2.0", - "arrow-schema 56.2.0", + "ahash", + "arrow-array", + "arrow-buffer", + "arrow-data", + "arrow-schema", "num", ] @@ -429,28 +256,11 @@ version = "54.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a21546b337ab304a32cfc0770f671db7411787586b45b78b4593ae78e64e2b03" dependencies = [ - "arrow-array 54.3.1", - "arrow-buffer 54.3.1", - "arrow-data 54.3.1", - "arrow-schema 54.3.1", - "arrow-select 54.3.1", - "memchr", - "num", - "regex", - "regex-syntax", -] - -[[package]] -name = "arrow-string" -version = "56.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53f5183c150fbc619eede22b861ea7c0eebed8eaac0333eaa7f6da5205fd504d" -dependencies = [ - "arrow-array 56.2.0", - "arrow-buffer 56.2.0", - "arrow-data 56.2.0", - "arrow-schema 56.2.0", - "arrow-select 56.2.0", + "arrow-array", + "arrow-buffer", + "arrow-data", + "arrow-schema", + "arrow-select", "memchr", "num", "regex", @@ -506,18 +316,6 @@ version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" -[[package]] -name = "bitvec" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - [[package]] name = "block-buffer" version = "0.10.4" @@ -527,57 +325,12 @@ dependencies = [ "generic-array", ] -[[package]] -name = "borsh" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1da5ab77c1437701eeff7c88d968729e7766172279eab0676857b3d63af7a6f" -dependencies = [ - "borsh-derive", - "cfg_aliases", -] - -[[package]] -name = "borsh-derive" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0686c856aa6aac0c4498f936d7d6a02df690f614c03e4d906d1018062b5c5e2c" -dependencies = [ - "once_cell", - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 2.0.111", -] - [[package]] name = "bumpalo" version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" -[[package]] -name = "bytecheck" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" -dependencies = [ - "bytecheck_derive", - "ptr_meta", - "simdutf8", -] - -[[package]] -name = "bytecheck_derive" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "bytecount" version = "0.6.9" @@ -596,12 +349,6 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" -[[package]] -name = "cast" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" - [[package]] name = "cc" version = "1.2.49" @@ -761,15 +508,6 @@ dependencies = [ "libc", ] -[[package]] -name = "crc32fast" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" -dependencies = [ - "cfg-if", -] - [[package]] name = "crossbeam-utils" version = "0.8.21" @@ -879,17 +617,6 @@ dependencies = [ "powerfmt", ] -[[package]] -name = "derive_arbitrary" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.111", -] - [[package]] name = "derive_more" version = "0.99.20" @@ -968,23 +695,6 @@ dependencies = [ "dtoa", ] -[[package]] -name = "duckdb" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7eeb487dde618b9f6ab26a451775ad5fac3fabe1ca2b64cbbe90b105f264ccd" -dependencies = [ - "arrow 56.1.0", - "cast", - "fallible-iterator", - "fallible-streaming-iterator", - "hashlink 0.10.0", - "libduckdb-sys", - "num-integer", - "rust_decimal", - "strum", -] - [[package]] name = "earcutr" version = "0.4.3" @@ -1041,18 +751,6 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" -[[package]] -name = "filetime" -version = "0.2.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc0505cd1b6fa6580283f6bdf70a73fcf4aba1184038c90902b92b3dd0df63ed" -dependencies = [ - "cfg-if", - "libc", - "libredox", - "windows-sys 0.60.2", -] - [[package]] name = "find-msvc-tools" version = "0.1.5" @@ -1069,17 +767,6 @@ dependencies = [ "rustc_version", ] -[[package]] -name = "flate2" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" -dependencies = [ - "crc32fast", - "libz-rs-sys", - "miniz_oxide", -] - [[package]] name = "float_next_after" version = "1.0.0" @@ -1107,12 +794,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - [[package]] name = "futf" version = "0.1.5" @@ -1225,7 +906,7 @@ dependencies = [ name = "garmin-cli" version = "2.1.0" dependencies = [ - "arrow 54.3.1", + "arrow", "base64", "bytes", "chrono", @@ -1233,7 +914,6 @@ dependencies = [ "comfy-table", "dashmap", "dirs", - "duckdb", "geo", "gpx", "hmac", @@ -1397,22 +1077,13 @@ dependencies = [ "byteorder", ] -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash 0.7.8", -] - [[package]] name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ - "ahash 0.8.12", + "ahash", ] [[package]] @@ -1441,15 +1112,6 @@ dependencies = [ "hashbrown 0.14.5", ] -[[package]] -name = "hashlink" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" -dependencies = [ - "hashbrown 0.15.5", -] - [[package]] name = "heapless" version = "0.8.0" @@ -1886,23 +1548,6 @@ version = "0.2.178" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" -[[package]] -name = "libduckdb-sys" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8c60c2d269e63ae5197e4fe9075efffed35dfda0095a5ac8b41f3c765b18456" -dependencies = [ - "cc", - "flate2", - "pkg-config", - "reqwest", - "serde", - "serde_json", - "tar", - "vcpkg", - "zip", -] - [[package]] name = "libm" version = "0.2.15" @@ -1917,7 +1562,6 @@ checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" dependencies = [ "bitflags 2.10.0", "libc", - "redox_syscall", ] [[package]] @@ -1931,15 +1575,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "libz-rs-sys" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15413ef615ad868d4d65dce091cb233b229419c7c0c4bcaa746c0901c49ff39c" -dependencies = [ - "zlib-rs", -] - [[package]] name = "linux-raw-sys" version = "0.11.0" @@ -2032,16 +1667,6 @@ dependencies = [ "unicase", ] -[[package]] -name = "miniz_oxide" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" -dependencies = [ - "adler2", - "simd-adler32", -] - [[package]] name = "mio" version = "1.1.1" @@ -2216,14 +1841,14 @@ version = "54.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfb15796ac6f56b429fd99e33ba133783ad75b27c36b4b5ce06f1f82cc97754e" dependencies = [ - "ahash 0.8.12", - "arrow-array 54.3.1", - "arrow-buffer 54.3.1", - "arrow-cast 54.3.1", - "arrow-data 54.3.1", + "ahash", + "arrow-array", + "arrow-buffer", + "arrow-cast", + "arrow-data", "arrow-ipc", - "arrow-schema 54.3.1", - "arrow-select 54.3.1", + "arrow-schema", + "arrow-select", "base64", "bytes", "chrono", @@ -2351,15 +1976,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" -[[package]] -name = "proc-macro-crate" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" -dependencies = [ - "toml_edit", -] - [[package]] name = "proc-macro-error" version = "1.0.4" @@ -2399,26 +2015,6 @@ version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" -[[package]] -name = "ptr_meta" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" -dependencies = [ - "ptr_meta_derive", -] - -[[package]] -name = "ptr_meta_derive" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "publicsuffix" version = "2.3.0" @@ -2499,12 +2095,6 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - [[package]] name = "rand" version = "0.8.5" @@ -2613,15 +2203,6 @@ version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" -[[package]] -name = "rend" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" -dependencies = [ - "bytecheck", -] - [[package]] name = "reqwest" version = "0.12.25" @@ -2632,7 +2213,6 @@ dependencies = [ "bytes", "cookie", "cookie_store", - "futures-channel", "futures-core", "futures-util", "http", @@ -2691,35 +2271,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "rkyv" -version = "0.7.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9008cd6385b9e161d8229e1f6549dd23c3d022f132a2ea37ac3a10ac4935779b" -dependencies = [ - "bitvec", - "bytecheck", - "bytes", - "hashbrown 0.12.3", - "ptr_meta", - "rend", - "rkyv_derive", - "seahash", - "tinyvec", - "uuid", -] - -[[package]] -name = "rkyv_derive" -version = "0.7.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "503d1d27590a2b0a3a4ca4c94755aa2875657196ecbf401a42eff41d7de532c0" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "robust" version = "1.2.0" @@ -2767,27 +2318,11 @@ dependencies = [ "bitflags 2.10.0", "fallible-iterator", "fallible-streaming-iterator", - "hashlink 0.9.1", + "hashlink", "libsqlite3-sys", "smallvec", ] -[[package]] -name = "rust_decimal" -version = "1.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35affe401787a9bd846712274d97654355d21b2a2c092a3139aabe31e9022282" -dependencies = [ - "arrayvec", - "borsh", - "bytes", - "num-traits", - "rand 0.8.5", - "rkyv", - "serde", - "serde_json", -] - [[package]] name = "rustc-hash" version = "2.1.1" @@ -2875,7 +2410,7 @@ version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0e749d29b2064585327af5038a5a8eb73aeebad4a3472e83531a436563f7208" dependencies = [ - "ahash 0.8.12", + "ahash", "cssparser", "ego-tree", "getopts", @@ -2885,12 +2420,6 @@ dependencies = [ "tendril", ] -[[package]] -name = "seahash" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" - [[package]] name = "selectors" version = "0.26.0" @@ -3012,18 +2541,6 @@ dependencies = [ "libc", ] -[[package]] -name = "simd-adler32" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" - -[[package]] -name = "simdutf8" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" - [[package]] name = "siphasher" version = "1.0.1" @@ -3113,27 +2630,6 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" -[[package]] -name = "strum" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" -dependencies = [ - "strum_macros", -] - -[[package]] -name = "strum_macros" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" -dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "syn 2.0.111", -] - [[package]] name = "subtle" version = "2.6.1" @@ -3205,23 +2701,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - -[[package]] -name = "tar" -version = "0.4.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d863878d212c87a19c1a610eb53bb01fe12951c0501cf5a0d65f724914a667a" -dependencies = [ - "filetime", - "libc", - "xattr", -] - [[package]] name = "tempfile" version = "3.23.0" @@ -3413,36 +2892,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "toml_datetime" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" -dependencies = [ - "serde_core", -] - -[[package]] -name = "toml_edit" -version = "0.23.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d7cbc3b4b49633d57a0509303158ca50de80ae32c265093b24c414705807832" -dependencies = [ - "indexmap", - "toml_datetime", - "toml_parser", - "winnow", -] - -[[package]] -name = "toml_parser" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" -dependencies = [ - "winnow", -] - [[package]] name = "tower" version = "0.5.2" @@ -3601,16 +3050,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" -[[package]] -name = "uuid" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - [[package]] name = "vcpkg" version = "0.2.15" @@ -4046,15 +3485,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" -[[package]] -name = "winnow" -version = "0.7.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" -dependencies = [ - "memchr", -] - [[package]] name = "wiremock" version = "0.6.5" @@ -4102,25 +3532,6 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" -[[package]] -name = "wyz" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" -dependencies = [ - "tap", -] - -[[package]] -name = "xattr" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" -dependencies = [ - "libc", - "rustix", -] - [[package]] name = "xml-rs" version = "0.8.28" @@ -4230,38 +3641,6 @@ dependencies = [ "syn 2.0.111", ] -[[package]] -name = "zip" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb2a05c7c36fde6c09b08576c9f7fb4cda705990f73b58fe011abf7dfb24168b" -dependencies = [ - "arbitrary", - "crc32fast", - "flate2", - "indexmap", - "memchr", - "zopfli", -] - -[[package]] -name = "zlib-rs" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51f936044d677be1a1168fae1d03b583a285a5dd9d8cbf7b24c23aa1fc775235" - -[[package]] -name = "zopfli" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f05cd8797d63865425ff89b5c4a48804f35ba0ce8d125800027ad6017d2b5249" -dependencies = [ - "bumpalo", - "crc32fast", - "log", - "simd-adler32", -] - [[package]] name = "zstd" version = "0.13.3" diff --git a/Cargo.toml b/Cargo.toml index 5a91bdc..9df2485 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,7 +48,6 @@ urlencoding = "2" rpassword = "7" # Database -duckdb = { version = "1.1", features = ["bundled"] } rusqlite = { version = "0.32", features = ["bundled"] } # Parquet/Arrow diff --git a/crates/garmin-cli/Cargo.toml b/crates/garmin-cli/Cargo.toml index f5d05d0..6b5db98 100644 --- a/crates/garmin-cli/Cargo.toml +++ b/crates/garmin-cli/Cargo.toml @@ -50,7 +50,6 @@ urlencoding.workspace = true rpassword.workspace = true # Database -duckdb.workspace = true rusqlite.workspace = true # Parquet/Arrow diff --git a/crates/garmin-cli/src/cli/commands/devices.rs b/crates/garmin-cli/src/cli/commands/devices.rs index cccb991..5f98f19 100644 --- a/crates/garmin-cli/src/cli/commands/devices.rs +++ b/crates/garmin-cli/src/cli/commands/devices.rs @@ -1,11 +1,13 @@ //! Device commands for garmin-cli -use duckdb::Connection; +use std::collections::HashMap; use crate::client::GarminClient; use crate::config::CredentialStore; +use crate::db::models::Activity; use crate::error::Result; use crate::storage::default_storage_path; +use crate::storage::ParquetStore; use super::auth::refresh_token; @@ -108,50 +110,8 @@ pub async fn history(storage_path: Option) -> Result<()> { return Ok(()); } - // Use DuckDB to query Parquet files with glob pattern - let conn = - Connection::open_in_memory().map_err(|e| crate::GarminError::Database(e.to_string()))?; - - let glob_pattern = format!("{}/*.parquet", activities_path.display()); - - // Query unique devices from activity metadata - let mut stmt = conn - .prepare(&format!( - "SELECT - json_extract_string(raw_json, '$.metadataDTO.deviceMetaDataDTO.deviceId') as device_id, - json_extract(raw_json, '$.metadataDTO.deviceMetaDataDTO.deviceTypePk') as device_type, - MIN(start_time_local) as first_activity, - MAX(start_time_local) as last_activity, - COUNT(*) as activity_count - FROM '{}' - WHERE raw_json IS NOT NULL - AND json_extract_string(raw_json, '$.metadataDTO.deviceMetaDataDTO.deviceId') IS NOT NULL - GROUP BY 1, 2 - ORDER BY first_activity", - glob_pattern - )) - .map_err(|e| crate::GarminError::Database(e.to_string()))?; - - #[allow(clippy::type_complexity)] - let devices: Vec<( - Option, - Option, - Option, - Option, - i64, - )> = stmt - .query_map([], |row| { - Ok(( - row.get::<_, Option>(0)?, - row.get::<_, Option>(1)?, - row.get::<_, Option>(2)?, - row.get::<_, Option>(3)?, - row.get::<_, i64>(4)?, - )) - }) - .map_err(|e| crate::GarminError::Database(e.to_string()))? - .filter_map(|r| r.ok()) - .collect(); + let store = ParquetStore::new(&storage_path); + let mut devices = collect_device_history(store.read_activities()?); if devices.is_empty() { println!("No device history found in synced activities."); @@ -166,27 +126,23 @@ pub async fn history(storage_path: Option) -> Result<()> { ); println!("{}", "-".repeat(65)); - for (device_id, device_type, first, last, count) in &devices { - let device_id_str = device_id.as_deref().unwrap_or("-"); - let device_type_str = device_type - .map(|t| t.to_string()) + devices.sort_by_key(|device| device.first_activity); + + for device in &devices { + let device_type_str = device + .device_type + .map(|device_type| device_type.to_string()) .unwrap_or_else(|| "-".to_string()); - let first_date = first - .as_ref() - .and_then(|s| s.split(' ').next()) - .unwrap_or("-"); - let last_date = last - .as_ref() - .and_then(|s| s.split(' ').next()) - .unwrap_or("-"); + let first_date = device.first_activity.date_naive().to_string(); + let last_date = device.last_activity.date_naive().to_string(); println!( "{:<15} {:<12} {:<12} {:<12} {:>10}", - truncate(device_id_str, 14), + truncate(&device.device_id, 14), truncate(&device_type_str, 11), first_date, last_date, - count + device.activity_count ); } @@ -198,3 +154,65 @@ pub async fn history(storage_path: Option) -> Result<()> { Ok(()) } + +#[derive(Debug)] +struct DeviceHistory { + device_id: String, + device_type: Option, + first_activity: chrono::DateTime, + last_activity: chrono::DateTime, + activity_count: usize, +} + +fn collect_device_history(activities: Vec) -> Vec { + let mut devices: HashMap<(String, Option), DeviceHistory> = HashMap::new(); + + for activity in activities { + let Some(start_time) = activity.start_time_local else { + continue; + }; + let Some((device_id, device_type)) = activity_device_metadata(&activity) else { + continue; + }; + + let entry = devices + .entry((device_id.clone(), device_type)) + .or_insert_with(|| DeviceHistory { + device_id, + device_type, + first_activity: start_time, + last_activity: start_time, + activity_count: 0, + }); + + entry.first_activity = entry.first_activity.min(start_time); + entry.last_activity = entry.last_activity.max(start_time); + entry.activity_count += 1; + } + + devices.into_values().collect() +} + +fn activity_device_metadata(activity: &Activity) -> Option<(String, Option)> { + let metadata = activity + .raw_json + .as_ref()? + .get("metadataDTO")? + .get("deviceMetaDataDTO")?; + + let device_id = metadata.get("deviceId").and_then(json_value_to_string)?; + let device_type = metadata.get("deviceTypePk").and_then(|value| { + value + .as_i64() + .or_else(|| value.as_str().and_then(|s| s.parse().ok())) + }); + + Some((device_id, device_type)) +} + +fn json_value_to_string(value: &serde_json::Value) -> Option { + value + .as_str() + .map(str::to_string) + .or_else(|| value.as_i64().map(|number| number.to_string())) +} diff --git a/crates/garmin-cli/src/storage/parquet.rs b/crates/garmin-cli/src/storage/parquet.rs index a4dbdd5..654674c 100644 --- a/crates/garmin-cli/src/storage/parquet.rs +++ b/crates/garmin-cli/src/storage/parquet.rs @@ -307,6 +307,34 @@ impl ParquetStore { Ok(activities) } + /// Read activities from all activity partitions. + pub fn read_activities(&self) -> Result> { + let dir = self.base_path.join(EntityType::Activities.dir_name()); + if !dir.exists() { + return Ok(Vec::new()); + } + + let mut activities = Vec::new(); + for entry in fs::read_dir(&dir).map_err(|e| { + GarminError::Database(format!( + "Failed to read activity directory {:?}: {}", + dir, e + )) + })? { + let path = entry + .map_err(|e| { + GarminError::Database(format!("Failed to read activity entry: {}", e)) + })? + .path(); + + if path.extension().and_then(|ext| ext.to_str()) == Some("parquet") { + activities.extend(self.read_activities_from_path(&path)?); + } + } + + Ok(activities) + } + fn activities_to_batch(activities: Vec<&Activity>) -> Result { let activity_id: Int64Array = activities.iter().map(|a| a.activity_id).collect(); let profile_id: Int32Array = activities.iter().map(|a| a.profile_id).collect(); @@ -2156,9 +2184,7 @@ mod tests { } #[test] - fn test_duckdb_glob_query() { - use duckdb::Connection; - + fn test_read_activities_from_all_partitions() { let temp = TempDir::new().unwrap(); let store = ParquetStore::new(temp.path()); @@ -2229,24 +2255,18 @@ mod tests { ]; store.upsert_activities(&activities).unwrap(); - // Use DuckDB to query all Parquet files with glob pattern - let conn = Connection::open_in_memory().unwrap(); - let glob_pattern = format!("{}/*.parquet", temp.path().join("activities").display()); - - let mut stmt = conn - .prepare(&format!( - "SELECT activity_id, activity_name FROM '{}' ORDER BY activity_id", - glob_pattern - )) - .unwrap(); - - let results: Vec<(i64, String)> = stmt - .query_map([], |row| { - Ok((row.get::<_, i64>(0)?, row.get::<_, String>(1)?)) - }) + let mut results: Vec<(i64, String)> = store + .read_activities() .unwrap() - .filter_map(|r| r.ok()) + .into_iter() + .map(|activity| { + ( + activity.activity_id, + activity.activity_name.unwrap_or_default(), + ) + }) .collect(); + results.sort_by_key(|(activity_id, _)| *activity_id); // Should see both activities from different partitions assert_eq!(results.len(), 2);