├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── building.md ├── do-build.sh ├── readme.md └── src └── lib.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "adler" 7 | version = "1.0.2" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 10 | 11 | [[package]] 12 | name = "ahash" 13 | version = "0.7.8" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" 16 | dependencies = [ 17 | "getrandom", 18 | "once_cell", 19 | "version_check", 20 | ] 21 | 22 | [[package]] 23 | name = "ahash" 24 | version = "0.8.11" 25 | source = "registry+https://github.com/rust-lang/crates.io-index" 26 | checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" 27 | dependencies = [ 28 | "cfg-if", 29 | "const-random", 30 | "getrandom", 31 | "once_cell", 32 | "version_check", 33 | "zerocopy", 34 | ] 35 | 36 | [[package]] 37 | name = "aho-corasick" 38 | version = "1.1.3" 39 | source = "registry+https://github.com/rust-lang/crates.io-index" 40 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 41 | dependencies = [ 42 | "memchr", 43 | ] 44 | 45 | [[package]] 46 | name = "allocator-api2" 47 | version = "0.2.18" 48 | source = "registry+https://github.com/rust-lang/crates.io-index" 49 | checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" 50 | 51 | [[package]] 52 | name = "android-tzdata" 53 | version = "0.1.1" 54 | source = "registry+https://github.com/rust-lang/crates.io-index" 55 | checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" 56 | 57 | [[package]] 58 | name = "android_system_properties" 59 | version = "0.1.5" 60 | source = "registry+https://github.com/rust-lang/crates.io-index" 61 | checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" 62 | dependencies = [ 63 | "libc", 64 | ] 65 | 66 | [[package]] 67 | name = "arrayvec" 68 | version = "0.7.4" 69 | source = "registry+https://github.com/rust-lang/crates.io-index" 70 | checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" 71 | 72 | [[package]] 73 | name = "arrow" 74 | version = "52.0.0" 75 | source = "registry+https://github.com/rust-lang/crates.io-index" 76 | checksum = "7ae9728f104939be6d8d9b368a354b4929b0569160ea1641f0721b55a861ce38" 77 | dependencies = [ 78 | "arrow-arith", 79 | "arrow-array", 80 | "arrow-buffer", 81 | "arrow-cast", 82 | "arrow-data", 83 | "arrow-ord", 84 | "arrow-row", 85 | "arrow-schema", 86 | "arrow-select", 87 | "arrow-string", 88 | ] 89 | 90 | [[package]] 91 | name = "arrow-arith" 92 | version = "52.0.0" 93 | source = "registry+https://github.com/rust-lang/crates.io-index" 94 | checksum = "a7029a5b3efbeafbf4a12d12dc16b8f9e9bff20a410b8c25c5d28acc089e1043" 95 | dependencies = [ 96 | "arrow-array", 97 | "arrow-buffer", 98 | "arrow-data", 99 | "arrow-schema", 100 | "chrono", 101 | "half", 102 | "num", 103 | ] 104 | 105 | [[package]] 106 | name = "arrow-array" 107 | version = "52.0.0" 108 | source = "registry+https://github.com/rust-lang/crates.io-index" 109 | checksum = "d33238427c60271710695f17742f45b1a5dc5bcfc5c15331c25ddfe7abf70d97" 110 | dependencies = [ 111 | "ahash 0.8.11", 112 | "arrow-buffer", 113 | "arrow-data", 114 | "arrow-schema", 115 | "chrono", 116 | "half", 117 | "hashbrown 0.14.5", 118 | "num", 119 | ] 120 | 121 | [[package]] 122 | name = "arrow-buffer" 123 | version = "52.0.0" 124 | source = "registry+https://github.com/rust-lang/crates.io-index" 125 | checksum = "fe9b95e825ae838efaf77e366c00d3fc8cca78134c9db497d6bda425f2e7b7c1" 126 | dependencies = [ 127 | "bytes", 128 | "half", 129 | "num", 130 | ] 131 | 132 | [[package]] 133 | name = "arrow-cast" 134 | version = "52.0.0" 135 | source = "registry+https://github.com/rust-lang/crates.io-index" 136 | checksum = "87cf8385a9d5b5fcde771661dd07652b79b9139fea66193eda6a88664400ccab" 137 | dependencies = [ 138 | "arrow-array", 139 | "arrow-buffer", 140 | "arrow-data", 141 | "arrow-schema", 142 | "arrow-select", 143 | "atoi", 144 | "base64", 145 | "chrono", 146 | "comfy-table", 147 | "half", 148 | "lexical-core", 149 | "num", 150 | "ryu", 151 | ] 152 | 153 | [[package]] 154 | name = "arrow-data" 155 | version = "52.0.0" 156 | source = "registry+https://github.com/rust-lang/crates.io-index" 157 | checksum = "cb29be98f987bcf217b070512bb7afba2f65180858bca462edf4a39d84a23e10" 158 | dependencies = [ 159 | "arrow-buffer", 160 | "arrow-schema", 161 | "half", 162 | "num", 163 | ] 164 | 165 | [[package]] 166 | name = "arrow-ord" 167 | version = "52.0.0" 168 | source = "registry+https://github.com/rust-lang/crates.io-index" 169 | checksum = "fcb56ed1547004e12203652f12fe12e824161ff9d1e5cf2a7dc4ff02ba94f413" 170 | dependencies = [ 171 | "arrow-array", 172 | "arrow-buffer", 173 | "arrow-data", 174 | "arrow-schema", 175 | "arrow-select", 176 | "half", 177 | "num", 178 | ] 179 | 180 | [[package]] 181 | name = "arrow-row" 182 | version = "52.0.0" 183 | source = "registry+https://github.com/rust-lang/crates.io-index" 184 | checksum = "575b42f1fc588f2da6977b94a5ca565459f5ab07b60545e17243fb9a7ed6d43e" 185 | dependencies = [ 186 | "ahash 0.8.11", 187 | "arrow-array", 188 | "arrow-buffer", 189 | "arrow-data", 190 | "arrow-schema", 191 | "half", 192 | "hashbrown 0.14.5", 193 | ] 194 | 195 | [[package]] 196 | name = "arrow-schema" 197 | version = "52.0.0" 198 | source = "registry+https://github.com/rust-lang/crates.io-index" 199 | checksum = "32aae6a60458a2389c0da89c9de0b7932427776127da1a738e2efc21d32f3393" 200 | dependencies = [ 201 | "bitflags 2.5.0", 202 | ] 203 | 204 | [[package]] 205 | name = "arrow-select" 206 | version = "52.0.0" 207 | source = "registry+https://github.com/rust-lang/crates.io-index" 208 | checksum = "de36abaef8767b4220d7b4a8c2fe5ffc78b47db81b03d77e2136091c3ba39102" 209 | dependencies = [ 210 | "ahash 0.8.11", 211 | "arrow-array", 212 | "arrow-buffer", 213 | "arrow-data", 214 | "arrow-schema", 215 | "num", 216 | ] 217 | 218 | [[package]] 219 | name = "arrow-string" 220 | version = "52.0.0" 221 | source = "registry+https://github.com/rust-lang/crates.io-index" 222 | checksum = "e435ada8409bcafc910bc3e0077f532a4daa20e99060a496685c0e3e53cc2597" 223 | dependencies = [ 224 | "arrow-array", 225 | "arrow-buffer", 226 | "arrow-data", 227 | "arrow-schema", 228 | "arrow-select", 229 | "memchr", 230 | "num", 231 | "regex", 232 | "regex-syntax", 233 | ] 234 | 235 | [[package]] 236 | name = "atoi" 237 | version = "2.0.0" 238 | source = "registry+https://github.com/rust-lang/crates.io-index" 239 | checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" 240 | dependencies = [ 241 | "num-traits", 242 | ] 243 | 244 | [[package]] 245 | name = "autocfg" 246 | version = "1.3.0" 247 | source = "registry+https://github.com/rust-lang/crates.io-index" 248 | checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" 249 | 250 | [[package]] 251 | name = "base64" 252 | version = "0.22.1" 253 | source = "registry+https://github.com/rust-lang/crates.io-index" 254 | checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" 255 | 256 | [[package]] 257 | name = "bindgen" 258 | version = "0.69.4" 259 | source = "registry+https://github.com/rust-lang/crates.io-index" 260 | checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" 261 | dependencies = [ 262 | "bitflags 2.5.0", 263 | "cexpr", 264 | "clang-sys", 265 | "itertools", 266 | "lazy_static", 267 | "lazycell", 268 | "proc-macro2", 269 | "quote", 270 | "regex", 271 | "rustc-hash", 272 | "shlex", 273 | "syn 2.0.65", 274 | ] 275 | 276 | [[package]] 277 | name = "bitflags" 278 | version = "1.3.2" 279 | source = "registry+https://github.com/rust-lang/crates.io-index" 280 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 281 | 282 | [[package]] 283 | name = "bitflags" 284 | version = "2.5.0" 285 | source = "registry+https://github.com/rust-lang/crates.io-index" 286 | checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" 287 | 288 | [[package]] 289 | name = "bitvec" 290 | version = "1.0.1" 291 | source = "registry+https://github.com/rust-lang/crates.io-index" 292 | checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" 293 | dependencies = [ 294 | "funty", 295 | "radium", 296 | "tap", 297 | "wyz", 298 | ] 299 | 300 | [[package]] 301 | name = "borsh" 302 | version = "1.5.0" 303 | source = "registry+https://github.com/rust-lang/crates.io-index" 304 | checksum = "dbe5b10e214954177fb1dc9fbd20a1a2608fe99e6c832033bdc7cea287a20d77" 305 | dependencies = [ 306 | "borsh-derive", 307 | "cfg_aliases", 308 | ] 309 | 310 | [[package]] 311 | name = "borsh-derive" 312 | version = "1.5.0" 313 | source = "registry+https://github.com/rust-lang/crates.io-index" 314 | checksum = "d7a8646f94ab393e43e8b35a2558b1624bed28b97ee09c5d15456e3c9463f46d" 315 | dependencies = [ 316 | "once_cell", 317 | "proc-macro-crate", 318 | "proc-macro2", 319 | "quote", 320 | "syn 2.0.65", 321 | "syn_derive", 322 | ] 323 | 324 | [[package]] 325 | name = "bumpalo" 326 | version = "3.16.0" 327 | source = "registry+https://github.com/rust-lang/crates.io-index" 328 | checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" 329 | 330 | [[package]] 331 | name = "bytecheck" 332 | version = "0.6.12" 333 | source = "registry+https://github.com/rust-lang/crates.io-index" 334 | checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" 335 | dependencies = [ 336 | "bytecheck_derive", 337 | "ptr_meta", 338 | "simdutf8", 339 | ] 340 | 341 | [[package]] 342 | name = "bytecheck_derive" 343 | version = "0.6.12" 344 | source = "registry+https://github.com/rust-lang/crates.io-index" 345 | checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" 346 | dependencies = [ 347 | "proc-macro2", 348 | "quote", 349 | "syn 1.0.109", 350 | ] 351 | 352 | [[package]] 353 | name = "bytes" 354 | version = "1.6.0" 355 | source = "registry+https://github.com/rust-lang/crates.io-index" 356 | checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" 357 | 358 | [[package]] 359 | name = "cast" 360 | version = "0.3.0" 361 | source = "registry+https://github.com/rust-lang/crates.io-index" 362 | checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" 363 | 364 | [[package]] 365 | name = "cc" 366 | version = "1.0.98" 367 | source = "registry+https://github.com/rust-lang/crates.io-index" 368 | checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" 369 | 370 | [[package]] 371 | name = "cexpr" 372 | version = "0.6.0" 373 | source = "registry+https://github.com/rust-lang/crates.io-index" 374 | checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" 375 | dependencies = [ 376 | "nom", 377 | ] 378 | 379 | [[package]] 380 | name = "cfg-if" 381 | version = "1.0.0" 382 | source = "registry+https://github.com/rust-lang/crates.io-index" 383 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 384 | 385 | [[package]] 386 | name = "cfg_aliases" 387 | version = "0.1.1" 388 | source = "registry+https://github.com/rust-lang/crates.io-index" 389 | checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" 390 | 391 | [[package]] 392 | name = "chrono" 393 | version = "0.4.38" 394 | source = "registry+https://github.com/rust-lang/crates.io-index" 395 | checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" 396 | dependencies = [ 397 | "android-tzdata", 398 | "iana-time-zone", 399 | "js-sys", 400 | "num-traits", 401 | "wasm-bindgen", 402 | "windows-targets", 403 | ] 404 | 405 | [[package]] 406 | name = "chrono-tz" 407 | version = "0.9.0" 408 | source = "registry+https://github.com/rust-lang/crates.io-index" 409 | checksum = "93698b29de5e97ad0ae26447b344c482a7284c737d9ddc5f9e52b74a336671bb" 410 | dependencies = [ 411 | "chrono", 412 | "chrono-tz-build", 413 | "phf", 414 | ] 415 | 416 | [[package]] 417 | name = "chrono-tz-build" 418 | version = "0.3.0" 419 | source = "registry+https://github.com/rust-lang/crates.io-index" 420 | checksum = "0c088aee841df9c3041febbb73934cfc39708749bf96dc827e3359cd39ef11b1" 421 | dependencies = [ 422 | "parse-zoneinfo", 423 | "phf", 424 | "phf_codegen", 425 | ] 426 | 427 | [[package]] 428 | name = "clang-sys" 429 | version = "1.7.0" 430 | source = "registry+https://github.com/rust-lang/crates.io-index" 431 | checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" 432 | dependencies = [ 433 | "glob", 434 | "libc", 435 | "libloading", 436 | ] 437 | 438 | [[package]] 439 | name = "comfy-table" 440 | version = "7.1.1" 441 | source = "registry+https://github.com/rust-lang/crates.io-index" 442 | checksum = "b34115915337defe99b2aff5c2ce6771e5fbc4079f4b506301f5cf394c8452f7" 443 | dependencies = [ 444 | "strum 0.26.2", 445 | "strum_macros 0.26.2", 446 | "unicode-width", 447 | ] 448 | 449 | [[package]] 450 | name = "const-random" 451 | version = "0.1.18" 452 | source = "registry+https://github.com/rust-lang/crates.io-index" 453 | checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" 454 | dependencies = [ 455 | "const-random-macro", 456 | ] 457 | 458 | [[package]] 459 | name = "const-random-macro" 460 | version = "0.1.16" 461 | source = "registry+https://github.com/rust-lang/crates.io-index" 462 | checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" 463 | dependencies = [ 464 | "getrandom", 465 | "once_cell", 466 | "tiny-keccak", 467 | ] 468 | 469 | [[package]] 470 | name = "core-foundation-sys" 471 | version = "0.8.6" 472 | source = "registry+https://github.com/rust-lang/crates.io-index" 473 | checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" 474 | 475 | [[package]] 476 | name = "crc32fast" 477 | version = "1.4.2" 478 | source = "registry+https://github.com/rust-lang/crates.io-index" 479 | checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" 480 | dependencies = [ 481 | "cfg-if", 482 | ] 483 | 484 | [[package]] 485 | name = "croner" 486 | version = "2.0.4" 487 | source = "registry+https://github.com/rust-lang/crates.io-index" 488 | checksum = "516aad5374ea0ea75a0f0f4512fb4e7ad46c5eeff9971cb8ebc8fd74f1cd16c1" 489 | dependencies = [ 490 | "chrono", 491 | ] 492 | 493 | [[package]] 494 | name = "crunchy" 495 | version = "0.2.2" 496 | source = "registry+https://github.com/rust-lang/crates.io-index" 497 | checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" 498 | 499 | [[package]] 500 | name = "duckdb" 501 | version = "1.0.0" 502 | dependencies = [ 503 | "arrow", 504 | "cast", 505 | "duckdb-loadable-macros 0.1.1", 506 | "fallible-iterator", 507 | "fallible-streaming-iterator", 508 | "hashlink", 509 | "libduckdb-sys", 510 | "memchr", 511 | "num-integer", 512 | "rust_decimal", 513 | "smallvec", 514 | "strum 0.25.0", 515 | ] 516 | 517 | [[package]] 518 | name = "duckdb-crontab-extension" 519 | version = "0.1.0" 520 | dependencies = [ 521 | "chrono", 522 | "chrono-tz", 523 | "croner", 524 | "duckdb", 525 | "duckdb-loadable-macros 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 526 | "libduckdb-sys", 527 | ] 528 | 529 | [[package]] 530 | name = "duckdb-loadable-macros" 531 | version = "0.1.1" 532 | dependencies = [ 533 | "proc-macro2", 534 | "quote", 535 | "syn 2.0.65", 536 | ] 537 | 538 | [[package]] 539 | name = "duckdb-loadable-macros" 540 | version = "0.1.1" 541 | source = "registry+https://github.com/rust-lang/crates.io-index" 542 | checksum = "38bb1181a36f31195c106382781836d80abdc665cd23bf9b7ebf2d3e88df9851" 543 | dependencies = [ 544 | "proc-macro2", 545 | "quote", 546 | "syn 2.0.65", 547 | ] 548 | 549 | [[package]] 550 | name = "either" 551 | version = "1.12.0" 552 | source = "registry+https://github.com/rust-lang/crates.io-index" 553 | checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" 554 | 555 | [[package]] 556 | name = "equivalent" 557 | version = "1.0.1" 558 | source = "registry+https://github.com/rust-lang/crates.io-index" 559 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" 560 | 561 | [[package]] 562 | name = "errno" 563 | version = "0.3.9" 564 | source = "registry+https://github.com/rust-lang/crates.io-index" 565 | checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" 566 | dependencies = [ 567 | "libc", 568 | "windows-sys", 569 | ] 570 | 571 | [[package]] 572 | name = "fallible-iterator" 573 | version = "0.3.0" 574 | source = "registry+https://github.com/rust-lang/crates.io-index" 575 | checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" 576 | 577 | [[package]] 578 | name = "fallible-streaming-iterator" 579 | version = "0.1.9" 580 | source = "registry+https://github.com/rust-lang/crates.io-index" 581 | checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" 582 | 583 | [[package]] 584 | name = "filetime" 585 | version = "0.2.23" 586 | source = "registry+https://github.com/rust-lang/crates.io-index" 587 | checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" 588 | dependencies = [ 589 | "cfg-if", 590 | "libc", 591 | "redox_syscall", 592 | "windows-sys", 593 | ] 594 | 595 | [[package]] 596 | name = "flate2" 597 | version = "1.0.30" 598 | source = "registry+https://github.com/rust-lang/crates.io-index" 599 | checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" 600 | dependencies = [ 601 | "crc32fast", 602 | "miniz_oxide", 603 | ] 604 | 605 | [[package]] 606 | name = "funty" 607 | version = "2.0.0" 608 | source = "registry+https://github.com/rust-lang/crates.io-index" 609 | checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" 610 | 611 | [[package]] 612 | name = "getrandom" 613 | version = "0.2.15" 614 | source = "registry+https://github.com/rust-lang/crates.io-index" 615 | checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" 616 | dependencies = [ 617 | "cfg-if", 618 | "libc", 619 | "wasi", 620 | ] 621 | 622 | [[package]] 623 | name = "glob" 624 | version = "0.3.1" 625 | source = "registry+https://github.com/rust-lang/crates.io-index" 626 | checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" 627 | 628 | [[package]] 629 | name = "half" 630 | version = "2.4.1" 631 | source = "registry+https://github.com/rust-lang/crates.io-index" 632 | checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" 633 | dependencies = [ 634 | "cfg-if", 635 | "crunchy", 636 | "num-traits", 637 | ] 638 | 639 | [[package]] 640 | name = "hashbrown" 641 | version = "0.12.3" 642 | source = "registry+https://github.com/rust-lang/crates.io-index" 643 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 644 | dependencies = [ 645 | "ahash 0.7.8", 646 | ] 647 | 648 | [[package]] 649 | name = "hashbrown" 650 | version = "0.14.5" 651 | source = "registry+https://github.com/rust-lang/crates.io-index" 652 | checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" 653 | dependencies = [ 654 | "ahash 0.8.11", 655 | "allocator-api2", 656 | ] 657 | 658 | [[package]] 659 | name = "hashlink" 660 | version = "0.8.4" 661 | source = "registry+https://github.com/rust-lang/crates.io-index" 662 | checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" 663 | dependencies = [ 664 | "hashbrown 0.14.5", 665 | ] 666 | 667 | [[package]] 668 | name = "heck" 669 | version = "0.4.1" 670 | source = "registry+https://github.com/rust-lang/crates.io-index" 671 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" 672 | 673 | [[package]] 674 | name = "iana-time-zone" 675 | version = "0.1.60" 676 | source = "registry+https://github.com/rust-lang/crates.io-index" 677 | checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" 678 | dependencies = [ 679 | "android_system_properties", 680 | "core-foundation-sys", 681 | "iana-time-zone-haiku", 682 | "js-sys", 683 | "wasm-bindgen", 684 | "windows-core", 685 | ] 686 | 687 | [[package]] 688 | name = "iana-time-zone-haiku" 689 | version = "0.1.2" 690 | source = "registry+https://github.com/rust-lang/crates.io-index" 691 | checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" 692 | dependencies = [ 693 | "cc", 694 | ] 695 | 696 | [[package]] 697 | name = "indexmap" 698 | version = "2.2.6" 699 | source = "registry+https://github.com/rust-lang/crates.io-index" 700 | checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" 701 | dependencies = [ 702 | "equivalent", 703 | "hashbrown 0.14.5", 704 | ] 705 | 706 | [[package]] 707 | name = "itertools" 708 | version = "0.12.1" 709 | source = "registry+https://github.com/rust-lang/crates.io-index" 710 | checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" 711 | dependencies = [ 712 | "either", 713 | ] 714 | 715 | [[package]] 716 | name = "itoa" 717 | version = "1.0.11" 718 | source = "registry+https://github.com/rust-lang/crates.io-index" 719 | checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" 720 | 721 | [[package]] 722 | name = "js-sys" 723 | version = "0.3.69" 724 | source = "registry+https://github.com/rust-lang/crates.io-index" 725 | checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" 726 | dependencies = [ 727 | "wasm-bindgen", 728 | ] 729 | 730 | [[package]] 731 | name = "lazy_static" 732 | version = "1.4.0" 733 | source = "registry+https://github.com/rust-lang/crates.io-index" 734 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 735 | 736 | [[package]] 737 | name = "lazycell" 738 | version = "1.3.0" 739 | source = "registry+https://github.com/rust-lang/crates.io-index" 740 | checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" 741 | 742 | [[package]] 743 | name = "lexical-core" 744 | version = "0.8.5" 745 | source = "registry+https://github.com/rust-lang/crates.io-index" 746 | checksum = "2cde5de06e8d4c2faabc400238f9ae1c74d5412d03a7bd067645ccbc47070e46" 747 | dependencies = [ 748 | "lexical-parse-float", 749 | "lexical-parse-integer", 750 | "lexical-util", 751 | "lexical-write-float", 752 | "lexical-write-integer", 753 | ] 754 | 755 | [[package]] 756 | name = "lexical-parse-float" 757 | version = "0.8.5" 758 | source = "registry+https://github.com/rust-lang/crates.io-index" 759 | checksum = "683b3a5ebd0130b8fb52ba0bdc718cc56815b6a097e28ae5a6997d0ad17dc05f" 760 | dependencies = [ 761 | "lexical-parse-integer", 762 | "lexical-util", 763 | "static_assertions", 764 | ] 765 | 766 | [[package]] 767 | name = "lexical-parse-integer" 768 | version = "0.8.6" 769 | source = "registry+https://github.com/rust-lang/crates.io-index" 770 | checksum = "6d0994485ed0c312f6d965766754ea177d07f9c00c9b82a5ee62ed5b47945ee9" 771 | dependencies = [ 772 | "lexical-util", 773 | "static_assertions", 774 | ] 775 | 776 | [[package]] 777 | name = "lexical-util" 778 | version = "0.8.5" 779 | source = "registry+https://github.com/rust-lang/crates.io-index" 780 | checksum = "5255b9ff16ff898710eb9eb63cb39248ea8a5bb036bea8085b1a767ff6c4e3fc" 781 | dependencies = [ 782 | "static_assertions", 783 | ] 784 | 785 | [[package]] 786 | name = "lexical-write-float" 787 | version = "0.8.5" 788 | source = "registry+https://github.com/rust-lang/crates.io-index" 789 | checksum = "accabaa1c4581f05a3923d1b4cfd124c329352288b7b9da09e766b0668116862" 790 | dependencies = [ 791 | "lexical-util", 792 | "lexical-write-integer", 793 | "static_assertions", 794 | ] 795 | 796 | [[package]] 797 | name = "lexical-write-integer" 798 | version = "0.8.5" 799 | source = "registry+https://github.com/rust-lang/crates.io-index" 800 | checksum = "e1b6f3d1f4422866b68192d62f77bc5c700bee84f3069f2469d7bc8c77852446" 801 | dependencies = [ 802 | "lexical-util", 803 | "static_assertions", 804 | ] 805 | 806 | [[package]] 807 | name = "libc" 808 | version = "0.2.155" 809 | source = "registry+https://github.com/rust-lang/crates.io-index" 810 | checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" 811 | 812 | [[package]] 813 | name = "libduckdb-sys" 814 | version = "1.0.0" 815 | dependencies = [ 816 | "autocfg", 817 | "bindgen", 818 | "flate2", 819 | "pkg-config", 820 | "serde", 821 | "serde_json", 822 | "tar", 823 | "vcpkg", 824 | ] 825 | 826 | [[package]] 827 | name = "libloading" 828 | version = "0.8.3" 829 | source = "registry+https://github.com/rust-lang/crates.io-index" 830 | checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" 831 | dependencies = [ 832 | "cfg-if", 833 | "windows-targets", 834 | ] 835 | 836 | [[package]] 837 | name = "libm" 838 | version = "0.2.8" 839 | source = "registry+https://github.com/rust-lang/crates.io-index" 840 | checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" 841 | 842 | [[package]] 843 | name = "linux-raw-sys" 844 | version = "0.4.14" 845 | source = "registry+https://github.com/rust-lang/crates.io-index" 846 | checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" 847 | 848 | [[package]] 849 | name = "log" 850 | version = "0.4.21" 851 | source = "registry+https://github.com/rust-lang/crates.io-index" 852 | checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" 853 | 854 | [[package]] 855 | name = "memchr" 856 | version = "2.7.2" 857 | source = "registry+https://github.com/rust-lang/crates.io-index" 858 | checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" 859 | 860 | [[package]] 861 | name = "minimal-lexical" 862 | version = "0.2.1" 863 | source = "registry+https://github.com/rust-lang/crates.io-index" 864 | checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 865 | 866 | [[package]] 867 | name = "miniz_oxide" 868 | version = "0.7.3" 869 | source = "registry+https://github.com/rust-lang/crates.io-index" 870 | checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" 871 | dependencies = [ 872 | "adler", 873 | ] 874 | 875 | [[package]] 876 | name = "nom" 877 | version = "7.1.3" 878 | source = "registry+https://github.com/rust-lang/crates.io-index" 879 | checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" 880 | dependencies = [ 881 | "memchr", 882 | "minimal-lexical", 883 | ] 884 | 885 | [[package]] 886 | name = "num" 887 | version = "0.4.3" 888 | source = "registry+https://github.com/rust-lang/crates.io-index" 889 | checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" 890 | dependencies = [ 891 | "num-bigint", 892 | "num-complex", 893 | "num-integer", 894 | "num-iter", 895 | "num-rational", 896 | "num-traits", 897 | ] 898 | 899 | [[package]] 900 | name = "num-bigint" 901 | version = "0.4.5" 902 | source = "registry+https://github.com/rust-lang/crates.io-index" 903 | checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" 904 | dependencies = [ 905 | "num-integer", 906 | "num-traits", 907 | ] 908 | 909 | [[package]] 910 | name = "num-complex" 911 | version = "0.4.6" 912 | source = "registry+https://github.com/rust-lang/crates.io-index" 913 | checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" 914 | dependencies = [ 915 | "num-traits", 916 | ] 917 | 918 | [[package]] 919 | name = "num-integer" 920 | version = "0.1.46" 921 | source = "registry+https://github.com/rust-lang/crates.io-index" 922 | checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" 923 | dependencies = [ 924 | "num-traits", 925 | ] 926 | 927 | [[package]] 928 | name = "num-iter" 929 | version = "0.1.45" 930 | source = "registry+https://github.com/rust-lang/crates.io-index" 931 | checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" 932 | dependencies = [ 933 | "autocfg", 934 | "num-integer", 935 | "num-traits", 936 | ] 937 | 938 | [[package]] 939 | name = "num-rational" 940 | version = "0.4.2" 941 | source = "registry+https://github.com/rust-lang/crates.io-index" 942 | checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" 943 | dependencies = [ 944 | "num-bigint", 945 | "num-integer", 946 | "num-traits", 947 | ] 948 | 949 | [[package]] 950 | name = "num-traits" 951 | version = "0.2.19" 952 | source = "registry+https://github.com/rust-lang/crates.io-index" 953 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 954 | dependencies = [ 955 | "autocfg", 956 | "libm", 957 | ] 958 | 959 | [[package]] 960 | name = "once_cell" 961 | version = "1.19.0" 962 | source = "registry+https://github.com/rust-lang/crates.io-index" 963 | checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" 964 | 965 | [[package]] 966 | name = "parse-zoneinfo" 967 | version = "0.3.1" 968 | source = "registry+https://github.com/rust-lang/crates.io-index" 969 | checksum = "1f2a05b18d44e2957b88f96ba460715e295bc1d7510468a2f3d3b44535d26c24" 970 | dependencies = [ 971 | "regex", 972 | ] 973 | 974 | [[package]] 975 | name = "phf" 976 | version = "0.11.2" 977 | source = "registry+https://github.com/rust-lang/crates.io-index" 978 | checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" 979 | dependencies = [ 980 | "phf_shared", 981 | ] 982 | 983 | [[package]] 984 | name = "phf_codegen" 985 | version = "0.11.2" 986 | source = "registry+https://github.com/rust-lang/crates.io-index" 987 | checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" 988 | dependencies = [ 989 | "phf_generator", 990 | "phf_shared", 991 | ] 992 | 993 | [[package]] 994 | name = "phf_generator" 995 | version = "0.11.2" 996 | source = "registry+https://github.com/rust-lang/crates.io-index" 997 | checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" 998 | dependencies = [ 999 | "phf_shared", 1000 | "rand", 1001 | ] 1002 | 1003 | [[package]] 1004 | name = "phf_shared" 1005 | version = "0.11.2" 1006 | source = "registry+https://github.com/rust-lang/crates.io-index" 1007 | checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" 1008 | dependencies = [ 1009 | "siphasher", 1010 | ] 1011 | 1012 | [[package]] 1013 | name = "pkg-config" 1014 | version = "0.3.30" 1015 | source = "registry+https://github.com/rust-lang/crates.io-index" 1016 | checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" 1017 | 1018 | [[package]] 1019 | name = "ppv-lite86" 1020 | version = "0.2.17" 1021 | source = "registry+https://github.com/rust-lang/crates.io-index" 1022 | checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" 1023 | 1024 | [[package]] 1025 | name = "proc-macro-crate" 1026 | version = "3.1.0" 1027 | source = "registry+https://github.com/rust-lang/crates.io-index" 1028 | checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" 1029 | dependencies = [ 1030 | "toml_edit", 1031 | ] 1032 | 1033 | [[package]] 1034 | name = "proc-macro-error" 1035 | version = "1.0.4" 1036 | source = "registry+https://github.com/rust-lang/crates.io-index" 1037 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 1038 | dependencies = [ 1039 | "proc-macro-error-attr", 1040 | "proc-macro2", 1041 | "quote", 1042 | "version_check", 1043 | ] 1044 | 1045 | [[package]] 1046 | name = "proc-macro-error-attr" 1047 | version = "1.0.4" 1048 | source = "registry+https://github.com/rust-lang/crates.io-index" 1049 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 1050 | dependencies = [ 1051 | "proc-macro2", 1052 | "quote", 1053 | "version_check", 1054 | ] 1055 | 1056 | [[package]] 1057 | name = "proc-macro2" 1058 | version = "1.0.83" 1059 | source = "registry+https://github.com/rust-lang/crates.io-index" 1060 | checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43" 1061 | dependencies = [ 1062 | "unicode-ident", 1063 | ] 1064 | 1065 | [[package]] 1066 | name = "ptr_meta" 1067 | version = "0.1.4" 1068 | source = "registry+https://github.com/rust-lang/crates.io-index" 1069 | checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" 1070 | dependencies = [ 1071 | "ptr_meta_derive", 1072 | ] 1073 | 1074 | [[package]] 1075 | name = "ptr_meta_derive" 1076 | version = "0.1.4" 1077 | source = "registry+https://github.com/rust-lang/crates.io-index" 1078 | checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" 1079 | dependencies = [ 1080 | "proc-macro2", 1081 | "quote", 1082 | "syn 1.0.109", 1083 | ] 1084 | 1085 | [[package]] 1086 | name = "quote" 1087 | version = "1.0.36" 1088 | source = "registry+https://github.com/rust-lang/crates.io-index" 1089 | checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" 1090 | dependencies = [ 1091 | "proc-macro2", 1092 | ] 1093 | 1094 | [[package]] 1095 | name = "radium" 1096 | version = "0.7.0" 1097 | source = "registry+https://github.com/rust-lang/crates.io-index" 1098 | checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" 1099 | 1100 | [[package]] 1101 | name = "rand" 1102 | version = "0.8.5" 1103 | source = "registry+https://github.com/rust-lang/crates.io-index" 1104 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 1105 | dependencies = [ 1106 | "libc", 1107 | "rand_chacha", 1108 | "rand_core", 1109 | ] 1110 | 1111 | [[package]] 1112 | name = "rand_chacha" 1113 | version = "0.3.1" 1114 | source = "registry+https://github.com/rust-lang/crates.io-index" 1115 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 1116 | dependencies = [ 1117 | "ppv-lite86", 1118 | "rand_core", 1119 | ] 1120 | 1121 | [[package]] 1122 | name = "rand_core" 1123 | version = "0.6.4" 1124 | source = "registry+https://github.com/rust-lang/crates.io-index" 1125 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 1126 | dependencies = [ 1127 | "getrandom", 1128 | ] 1129 | 1130 | [[package]] 1131 | name = "redox_syscall" 1132 | version = "0.4.1" 1133 | source = "registry+https://github.com/rust-lang/crates.io-index" 1134 | checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" 1135 | dependencies = [ 1136 | "bitflags 1.3.2", 1137 | ] 1138 | 1139 | [[package]] 1140 | name = "regex" 1141 | version = "1.10.4" 1142 | source = "registry+https://github.com/rust-lang/crates.io-index" 1143 | checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" 1144 | dependencies = [ 1145 | "aho-corasick", 1146 | "memchr", 1147 | "regex-automata", 1148 | "regex-syntax", 1149 | ] 1150 | 1151 | [[package]] 1152 | name = "regex-automata" 1153 | version = "0.4.6" 1154 | source = "registry+https://github.com/rust-lang/crates.io-index" 1155 | checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" 1156 | dependencies = [ 1157 | "aho-corasick", 1158 | "memchr", 1159 | "regex-syntax", 1160 | ] 1161 | 1162 | [[package]] 1163 | name = "regex-syntax" 1164 | version = "0.8.3" 1165 | source = "registry+https://github.com/rust-lang/crates.io-index" 1166 | checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" 1167 | 1168 | [[package]] 1169 | name = "rend" 1170 | version = "0.4.2" 1171 | source = "registry+https://github.com/rust-lang/crates.io-index" 1172 | checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" 1173 | dependencies = [ 1174 | "bytecheck", 1175 | ] 1176 | 1177 | [[package]] 1178 | name = "rkyv" 1179 | version = "0.7.44" 1180 | source = "registry+https://github.com/rust-lang/crates.io-index" 1181 | checksum = "5cba464629b3394fc4dbc6f940ff8f5b4ff5c7aef40f29166fd4ad12acbc99c0" 1182 | dependencies = [ 1183 | "bitvec", 1184 | "bytecheck", 1185 | "bytes", 1186 | "hashbrown 0.12.3", 1187 | "ptr_meta", 1188 | "rend", 1189 | "rkyv_derive", 1190 | "seahash", 1191 | "tinyvec", 1192 | "uuid", 1193 | ] 1194 | 1195 | [[package]] 1196 | name = "rkyv_derive" 1197 | version = "0.7.44" 1198 | source = "registry+https://github.com/rust-lang/crates.io-index" 1199 | checksum = "a7dddfff8de25e6f62b9d64e6e432bf1c6736c57d20323e15ee10435fbda7c65" 1200 | dependencies = [ 1201 | "proc-macro2", 1202 | "quote", 1203 | "syn 1.0.109", 1204 | ] 1205 | 1206 | [[package]] 1207 | name = "rust_decimal" 1208 | version = "1.35.0" 1209 | source = "registry+https://github.com/rust-lang/crates.io-index" 1210 | checksum = "1790d1c4c0ca81211399e0e0af16333276f375209e71a37b67698a373db5b47a" 1211 | dependencies = [ 1212 | "arrayvec", 1213 | "borsh", 1214 | "bytes", 1215 | "num-traits", 1216 | "rand", 1217 | "rkyv", 1218 | "serde", 1219 | "serde_json", 1220 | ] 1221 | 1222 | [[package]] 1223 | name = "rustc-hash" 1224 | version = "1.1.0" 1225 | source = "registry+https://github.com/rust-lang/crates.io-index" 1226 | checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" 1227 | 1228 | [[package]] 1229 | name = "rustix" 1230 | version = "0.38.34" 1231 | source = "registry+https://github.com/rust-lang/crates.io-index" 1232 | checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" 1233 | dependencies = [ 1234 | "bitflags 2.5.0", 1235 | "errno", 1236 | "libc", 1237 | "linux-raw-sys", 1238 | "windows-sys", 1239 | ] 1240 | 1241 | [[package]] 1242 | name = "rustversion" 1243 | version = "1.0.17" 1244 | source = "registry+https://github.com/rust-lang/crates.io-index" 1245 | checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" 1246 | 1247 | [[package]] 1248 | name = "ryu" 1249 | version = "1.0.18" 1250 | source = "registry+https://github.com/rust-lang/crates.io-index" 1251 | checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" 1252 | 1253 | [[package]] 1254 | name = "seahash" 1255 | version = "4.1.0" 1256 | source = "registry+https://github.com/rust-lang/crates.io-index" 1257 | checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" 1258 | 1259 | [[package]] 1260 | name = "serde" 1261 | version = "1.0.202" 1262 | source = "registry+https://github.com/rust-lang/crates.io-index" 1263 | checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" 1264 | dependencies = [ 1265 | "serde_derive", 1266 | ] 1267 | 1268 | [[package]] 1269 | name = "serde_derive" 1270 | version = "1.0.202" 1271 | source = "registry+https://github.com/rust-lang/crates.io-index" 1272 | checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" 1273 | dependencies = [ 1274 | "proc-macro2", 1275 | "quote", 1276 | "syn 2.0.65", 1277 | ] 1278 | 1279 | [[package]] 1280 | name = "serde_json" 1281 | version = "1.0.117" 1282 | source = "registry+https://github.com/rust-lang/crates.io-index" 1283 | checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" 1284 | dependencies = [ 1285 | "itoa", 1286 | "ryu", 1287 | "serde", 1288 | ] 1289 | 1290 | [[package]] 1291 | name = "shlex" 1292 | version = "1.3.0" 1293 | source = "registry+https://github.com/rust-lang/crates.io-index" 1294 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 1295 | 1296 | [[package]] 1297 | name = "simdutf8" 1298 | version = "0.1.4" 1299 | source = "registry+https://github.com/rust-lang/crates.io-index" 1300 | checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" 1301 | 1302 | [[package]] 1303 | name = "siphasher" 1304 | version = "0.3.11" 1305 | source = "registry+https://github.com/rust-lang/crates.io-index" 1306 | checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" 1307 | 1308 | [[package]] 1309 | name = "smallvec" 1310 | version = "1.13.2" 1311 | source = "registry+https://github.com/rust-lang/crates.io-index" 1312 | checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" 1313 | 1314 | [[package]] 1315 | name = "static_assertions" 1316 | version = "1.1.0" 1317 | source = "registry+https://github.com/rust-lang/crates.io-index" 1318 | checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" 1319 | 1320 | [[package]] 1321 | name = "strum" 1322 | version = "0.25.0" 1323 | source = "registry+https://github.com/rust-lang/crates.io-index" 1324 | checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" 1325 | dependencies = [ 1326 | "strum_macros 0.25.3", 1327 | ] 1328 | 1329 | [[package]] 1330 | name = "strum" 1331 | version = "0.26.2" 1332 | source = "registry+https://github.com/rust-lang/crates.io-index" 1333 | checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" 1334 | 1335 | [[package]] 1336 | name = "strum_macros" 1337 | version = "0.25.3" 1338 | source = "registry+https://github.com/rust-lang/crates.io-index" 1339 | checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" 1340 | dependencies = [ 1341 | "heck", 1342 | "proc-macro2", 1343 | "quote", 1344 | "rustversion", 1345 | "syn 2.0.65", 1346 | ] 1347 | 1348 | [[package]] 1349 | name = "strum_macros" 1350 | version = "0.26.2" 1351 | source = "registry+https://github.com/rust-lang/crates.io-index" 1352 | checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" 1353 | dependencies = [ 1354 | "heck", 1355 | "proc-macro2", 1356 | "quote", 1357 | "rustversion", 1358 | "syn 2.0.65", 1359 | ] 1360 | 1361 | [[package]] 1362 | name = "syn" 1363 | version = "1.0.109" 1364 | source = "registry+https://github.com/rust-lang/crates.io-index" 1365 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" 1366 | dependencies = [ 1367 | "proc-macro2", 1368 | "quote", 1369 | "unicode-ident", 1370 | ] 1371 | 1372 | [[package]] 1373 | name = "syn" 1374 | version = "2.0.65" 1375 | source = "registry+https://github.com/rust-lang/crates.io-index" 1376 | checksum = "d2863d96a84c6439701d7a38f9de935ec562c8832cc55d1dde0f513b52fad106" 1377 | dependencies = [ 1378 | "proc-macro2", 1379 | "quote", 1380 | "unicode-ident", 1381 | ] 1382 | 1383 | [[package]] 1384 | name = "syn_derive" 1385 | version = "0.1.8" 1386 | source = "registry+https://github.com/rust-lang/crates.io-index" 1387 | checksum = "1329189c02ff984e9736652b1631330da25eaa6bc639089ed4915d25446cbe7b" 1388 | dependencies = [ 1389 | "proc-macro-error", 1390 | "proc-macro2", 1391 | "quote", 1392 | "syn 2.0.65", 1393 | ] 1394 | 1395 | [[package]] 1396 | name = "tap" 1397 | version = "1.0.1" 1398 | source = "registry+https://github.com/rust-lang/crates.io-index" 1399 | checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" 1400 | 1401 | [[package]] 1402 | name = "tar" 1403 | version = "0.4.40" 1404 | source = "registry+https://github.com/rust-lang/crates.io-index" 1405 | checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" 1406 | dependencies = [ 1407 | "filetime", 1408 | "libc", 1409 | "xattr", 1410 | ] 1411 | 1412 | [[package]] 1413 | name = "tiny-keccak" 1414 | version = "2.0.2" 1415 | source = "registry+https://github.com/rust-lang/crates.io-index" 1416 | checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" 1417 | dependencies = [ 1418 | "crunchy", 1419 | ] 1420 | 1421 | [[package]] 1422 | name = "tinyvec" 1423 | version = "1.6.0" 1424 | source = "registry+https://github.com/rust-lang/crates.io-index" 1425 | checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" 1426 | dependencies = [ 1427 | "tinyvec_macros", 1428 | ] 1429 | 1430 | [[package]] 1431 | name = "tinyvec_macros" 1432 | version = "0.1.1" 1433 | source = "registry+https://github.com/rust-lang/crates.io-index" 1434 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 1435 | 1436 | [[package]] 1437 | name = "toml_datetime" 1438 | version = "0.6.6" 1439 | source = "registry+https://github.com/rust-lang/crates.io-index" 1440 | checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" 1441 | 1442 | [[package]] 1443 | name = "toml_edit" 1444 | version = "0.21.1" 1445 | source = "registry+https://github.com/rust-lang/crates.io-index" 1446 | checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" 1447 | dependencies = [ 1448 | "indexmap", 1449 | "toml_datetime", 1450 | "winnow", 1451 | ] 1452 | 1453 | [[package]] 1454 | name = "unicode-ident" 1455 | version = "1.0.12" 1456 | source = "registry+https://github.com/rust-lang/crates.io-index" 1457 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" 1458 | 1459 | [[package]] 1460 | name = "unicode-width" 1461 | version = "0.1.12" 1462 | source = "registry+https://github.com/rust-lang/crates.io-index" 1463 | checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" 1464 | 1465 | [[package]] 1466 | name = "uuid" 1467 | version = "1.8.0" 1468 | source = "registry+https://github.com/rust-lang/crates.io-index" 1469 | checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" 1470 | 1471 | [[package]] 1472 | name = "vcpkg" 1473 | version = "0.2.15" 1474 | source = "registry+https://github.com/rust-lang/crates.io-index" 1475 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 1476 | 1477 | [[package]] 1478 | name = "version_check" 1479 | version = "0.9.4" 1480 | source = "registry+https://github.com/rust-lang/crates.io-index" 1481 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 1482 | 1483 | [[package]] 1484 | name = "wasi" 1485 | version = "0.11.0+wasi-snapshot-preview1" 1486 | source = "registry+https://github.com/rust-lang/crates.io-index" 1487 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1488 | 1489 | [[package]] 1490 | name = "wasm-bindgen" 1491 | version = "0.2.92" 1492 | source = "registry+https://github.com/rust-lang/crates.io-index" 1493 | checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" 1494 | dependencies = [ 1495 | "cfg-if", 1496 | "wasm-bindgen-macro", 1497 | ] 1498 | 1499 | [[package]] 1500 | name = "wasm-bindgen-backend" 1501 | version = "0.2.92" 1502 | source = "registry+https://github.com/rust-lang/crates.io-index" 1503 | checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" 1504 | dependencies = [ 1505 | "bumpalo", 1506 | "log", 1507 | "once_cell", 1508 | "proc-macro2", 1509 | "quote", 1510 | "syn 2.0.65", 1511 | "wasm-bindgen-shared", 1512 | ] 1513 | 1514 | [[package]] 1515 | name = "wasm-bindgen-macro" 1516 | version = "0.2.92" 1517 | source = "registry+https://github.com/rust-lang/crates.io-index" 1518 | checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" 1519 | dependencies = [ 1520 | "quote", 1521 | "wasm-bindgen-macro-support", 1522 | ] 1523 | 1524 | [[package]] 1525 | name = "wasm-bindgen-macro-support" 1526 | version = "0.2.92" 1527 | source = "registry+https://github.com/rust-lang/crates.io-index" 1528 | checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" 1529 | dependencies = [ 1530 | "proc-macro2", 1531 | "quote", 1532 | "syn 2.0.65", 1533 | "wasm-bindgen-backend", 1534 | "wasm-bindgen-shared", 1535 | ] 1536 | 1537 | [[package]] 1538 | name = "wasm-bindgen-shared" 1539 | version = "0.2.92" 1540 | source = "registry+https://github.com/rust-lang/crates.io-index" 1541 | checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" 1542 | 1543 | [[package]] 1544 | name = "windows-core" 1545 | version = "0.52.0" 1546 | source = "registry+https://github.com/rust-lang/crates.io-index" 1547 | checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" 1548 | dependencies = [ 1549 | "windows-targets", 1550 | ] 1551 | 1552 | [[package]] 1553 | name = "windows-sys" 1554 | version = "0.52.0" 1555 | source = "registry+https://github.com/rust-lang/crates.io-index" 1556 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 1557 | dependencies = [ 1558 | "windows-targets", 1559 | ] 1560 | 1561 | [[package]] 1562 | name = "windows-targets" 1563 | version = "0.52.5" 1564 | source = "registry+https://github.com/rust-lang/crates.io-index" 1565 | checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" 1566 | dependencies = [ 1567 | "windows_aarch64_gnullvm", 1568 | "windows_aarch64_msvc", 1569 | "windows_i686_gnu", 1570 | "windows_i686_gnullvm", 1571 | "windows_i686_msvc", 1572 | "windows_x86_64_gnu", 1573 | "windows_x86_64_gnullvm", 1574 | "windows_x86_64_msvc", 1575 | ] 1576 | 1577 | [[package]] 1578 | name = "windows_aarch64_gnullvm" 1579 | version = "0.52.5" 1580 | source = "registry+https://github.com/rust-lang/crates.io-index" 1581 | checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" 1582 | 1583 | [[package]] 1584 | name = "windows_aarch64_msvc" 1585 | version = "0.52.5" 1586 | source = "registry+https://github.com/rust-lang/crates.io-index" 1587 | checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" 1588 | 1589 | [[package]] 1590 | name = "windows_i686_gnu" 1591 | version = "0.52.5" 1592 | source = "registry+https://github.com/rust-lang/crates.io-index" 1593 | checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" 1594 | 1595 | [[package]] 1596 | name = "windows_i686_gnullvm" 1597 | version = "0.52.5" 1598 | source = "registry+https://github.com/rust-lang/crates.io-index" 1599 | checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" 1600 | 1601 | [[package]] 1602 | name = "windows_i686_msvc" 1603 | version = "0.52.5" 1604 | source = "registry+https://github.com/rust-lang/crates.io-index" 1605 | checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" 1606 | 1607 | [[package]] 1608 | name = "windows_x86_64_gnu" 1609 | version = "0.52.5" 1610 | source = "registry+https://github.com/rust-lang/crates.io-index" 1611 | checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" 1612 | 1613 | [[package]] 1614 | name = "windows_x86_64_gnullvm" 1615 | version = "0.52.5" 1616 | source = "registry+https://github.com/rust-lang/crates.io-index" 1617 | checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" 1618 | 1619 | [[package]] 1620 | name = "windows_x86_64_msvc" 1621 | version = "0.52.5" 1622 | source = "registry+https://github.com/rust-lang/crates.io-index" 1623 | checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" 1624 | 1625 | [[package]] 1626 | name = "winnow" 1627 | version = "0.5.40" 1628 | source = "registry+https://github.com/rust-lang/crates.io-index" 1629 | checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" 1630 | dependencies = [ 1631 | "memchr", 1632 | ] 1633 | 1634 | [[package]] 1635 | name = "wyz" 1636 | version = "0.5.1" 1637 | source = "registry+https://github.com/rust-lang/crates.io-index" 1638 | checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" 1639 | dependencies = [ 1640 | "tap", 1641 | ] 1642 | 1643 | [[package]] 1644 | name = "xattr" 1645 | version = "1.3.1" 1646 | source = "registry+https://github.com/rust-lang/crates.io-index" 1647 | checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" 1648 | dependencies = [ 1649 | "libc", 1650 | "linux-raw-sys", 1651 | "rustix", 1652 | ] 1653 | 1654 | [[package]] 1655 | name = "zerocopy" 1656 | version = "0.7.34" 1657 | source = "registry+https://github.com/rust-lang/crates.io-index" 1658 | checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" 1659 | dependencies = [ 1660 | "zerocopy-derive", 1661 | ] 1662 | 1663 | [[package]] 1664 | name = "zerocopy-derive" 1665 | version = "0.7.34" 1666 | source = "registry+https://github.com/rust-lang/crates.io-index" 1667 | checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" 1668 | dependencies = [ 1669 | "proc-macro2", 1670 | "quote", 1671 | "syn 2.0.65", 1672 | ] 1673 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "duckdb-crontab-extension" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [lib] 7 | name = "crontab" 8 | crate-type = ["cdylib"] 9 | 10 | [dependencies] 11 | chrono = "0.4.38" 12 | chrono-tz = "0.9.0" 13 | croner = "2.0.4" 14 | duckdb = { path = "./duckdb-rs/crates/duckdb", features = ["vtab-loadable", "buildtime_bindgen"] } 15 | duckdb-loadable-macros = "0.1.1" 16 | libduckdb-sys = { path = "./duckdb-rs/crates/libduckdb-sys" } 17 | 18 | 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2024 Rusty Conover 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /building.md: -------------------------------------------------------------------------------- 1 | # Building The Extension 2 | 3 | Building this DuckDB extension is a bit complicated since DuckDB does not currently have a C API for getting the timestamp value from a `duckdb_value`. 4 | 5 | I've created a branch of DuckDB that adds this support. 6 | 7 | https://github.com/rustyconover/duckdb/tree/feat_timestamp_duckdb_value 8 | 9 | Since Rust is being used to interface with DuckDB, the duckdb-rs crate must also be updated to expose the new functions from the DuckDB C API. 10 | 11 | https://github.com/rustyconover/duckdb-rs/tree/feat_add_timestamp_for_duckdb_value -------------------------------------------------------------------------------- /do-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | export BUILD_ROOT=`pwd` 5 | 6 | # It is assumed that the patched version of duckdb is built 7 | # under this directory called duckdb 8 | 9 | # It is also assumed the patched duckdb-rs is present in the 10 | # current directory under duckdb-rs 11 | 12 | export DUCKDB_LIB_DIR="$BUILD_ROOT/duckdb/build/debug/src/" 13 | export DUCKDB_INCLUDE_DIR="$BUILD_ROOT/duckdb/src/include/" 14 | cargo build 15 | 16 | 17 | EXTENSION_FILE=./target/debug/libcrontab.duckdb_extension 18 | 19 | cp ./target/debug/libcrontab.dylib $EXTENSION_FILE 20 | 21 | /bin/echo -n "osx_arm64" > duckdb_platform_out 22 | 23 | install_name_tool -add_rpath $BUILD_ROOT/duckdb/build/debug/src/ \ 24 | $EXTENSION_FILE 25 | 26 | # There needs to be some signing step performed here to add metadata to the extension. 27 | cmake -DEXTENSION=$EXTENSION_FILE \ 28 | -DDUCKDB_VERSION="2f818ce50d" \ 29 | -DEXTENSION_VERSION="0.0.1" \ 30 | -DPLATFORM_FILE=./duckdb_platform_out \ 31 | -DNULL_FILE=./duckdb/scripts/null.txt \ 32 | -P ./duckdb/scripts/append_metadata.cmake 33 | 34 | $BUILD_ROOT/duckdb/build/debug/duckdb \ 35 | -unsigned \ 36 | -c "load '$EXTENSION_FILE'; select * from cron('5 * * * *', start=get_current_timestamp(), until=date '2028-08-20'); " -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Cron Expressions For DuckDB 2 | 3 | ## Motivation 4 | 5 | Cron jobs are a fundamental tool for scheduling tasks, often used for analyzing system behavior or verifying the completeness of data collections. For instance, a task might be scheduled to run daily at 10:30 AM, while another runs every Tuesday at 3 PM. These times might be in different time zones, such as UTC or New York time. 6 | 7 | To efficiently compare these scheduled tasks against actual data, it’s beneficial to generate a list of expected timestamps directly within DuckDB. While DuckDB's `generate_series()` function can create a series of timestamps, it lacks the expressiveness needed for complex recurring patterns. I want to fill this with a new DuckDB extension that interprets cron expressions, leveraging the Rust crate [`croner`](https://crates.io/crates/croner). 8 | 9 | This extension introduces a table-returning function `cron()`, which calculates upcoming or past times that satisfy a given cron expression. 10 | 11 | ## Examples 12 | 13 | #### Basic Usage 14 | 15 | The `cron()` function returns the next timestamp for a given cron expression: 16 | 17 | ```sql 18 | -- This expression occurs every day at 5 AM. 19 | SELECT * FROM cron('0 5 * * *'); 20 | ┌─────────────────────┐ 21 | │ cron │ 22 | │ timestamp_s │ 23 | ├─────────────────────┤ 24 | │ 2024-05-26 05:00:00 │ 25 | └─────────────────────┘ 26 | ``` 27 | 28 | #### Future Timestamps 29 | 30 | To retrieve all future occurrences up to a specific date: 31 | 32 | ```sql 33 | select * from cron('0 5 * * *', until='2024-06-05'); 34 | ┌─────────────────────┐ 35 | │ cron │ 36 | │ timestamp_s │ 37 | ├─────────────────────┤ 38 | │ 2024-05-26 05:00:00 │ 39 | │ 2024-05-27 05:00:00 │ 40 | │ 2024-05-28 05:00:00 │ 41 | │ 2024-05-29 05:00:00 │ 42 | │ 2024-05-30 05:00:00 │ 43 | │ 2024-05-31 05:00:00 │ 44 | │ 2024-06-01 05:00:00 │ 45 | │ 2024-06-02 05:00:00 │ 46 | │ 2024-06-03 05:00:00 │ 47 | │ 2024-06-04 05:00:00 │ 48 | ├─────────────────────┤ 49 | │ 10 rows │ 50 | └─────────────────────┘ 51 | ```` 52 | 53 | #### Past Timestamps 54 | 55 | To retrieve occurrences within a past date range: 56 | 57 | ```sql 58 | select * from cron('0 5 * * *', until='2020-08-04', start='2020-08-01'); 59 | ┌─────────────────────┐ 60 | │ cron │ 61 | │ timestamp_s │ 62 | ├─────────────────────┤ 63 | │ 2020-08-01 05:00:00 │ 64 | │ 2020-08-02 05:00:00 │ 65 | │ 2020-08-03 05:00:00 │ 66 | └─────────────────────┘ 67 | ``` 68 | 69 | #### Timezone Handling 70 | 71 | Cron expressions can be evaluated in specific time zones: 72 | 73 | ```sql 74 | select * from 75 | cron( 76 | '0 5 * * *', 77 | until='2024-03-14 00:00:00', 78 | start='2024-03-08 01:58:00', 79 | timezone='America/New_York'); 80 | 81 | ┌─────────────────────┐ 82 | │ cron │ 83 | │ timestamp_s │ 84 | ├─────────────────────┤ 85 | │ 2024-03-08 10:00:00 │ 86 | │ 2024-03-09 10:00:00 │ 87 | │ 2024-03-10 09:00:00 │ 88 | │ 2024-03-11 09:00:00 │ 89 | │ 2024-03-12 09:00:00 │ 90 | │ 2024-03-13 09:00:00 │ 91 | └─────────────────────┘ 92 | ``` 93 | 94 | Changing DuckDB's timezone to match. 95 | 96 | ```sql 97 | set timezone to 'America/New_York'; 98 | 99 | select * from 100 | cron( 101 | '0 5 * * *', 102 | until='2024-03-14 00:00:00', 103 | start='2024-03-08 01:58:00', 104 | timezone='America/New_York'); 105 | ┌─────────────────────┐ 106 | │ cron │ 107 | │ timestamp_s │ 108 | ├─────────────────────┤ 109 | │ 2024-03-08 10:00:00 │ 110 | │ 2024-03-09 10:00:00 │ 111 | │ 2024-03-10 09:00:00 │ 112 | │ 2024-03-11 09:00:00 │ 113 | │ 2024-03-12 09:00:00 │ 114 | │ 2024-03-13 09:00:00 │ 115 | └─────────────────────┘ 116 | ``` 117 | 118 | #### Second Level Precision 119 | 120 | ```sql 121 | select * from cron('*/3 0 5 * * *', until='2024-05-30') limit 5; 122 | ┌─────────────────────┐ 123 | │ cron │ 124 | │ timestamp_s │ 125 | ├─────────────────────┤ 126 | │ 2024-05-26 05:00:00 │ 127 | │ 2024-05-26 05:00:03 │ 128 | │ 2024-05-26 05:00:06 │ 129 | │ 2024-05-26 05:00:09 │ 130 | │ 2024-05-26 05:00:12 │ 131 | └─────────────────────┘ 132 | ``` 133 | 134 | #### More complicated cron expressions 135 | 136 | Using cron expressions for specific days of the week: 137 | 138 | ```sql 139 | select * from cron('0 5 * * Mon', until='2024-09-30') limit 5; 140 | ┌─────────────────────┐ 141 | │ cron │ 142 | │ timestamp_s │ 143 | ├─────────────────────┤ 144 | │ 2024-05-27 05:00:00 │ 145 | │ 2024-06-03 05:00:00 │ 146 | │ 2024-06-10 05:00:00 │ 147 | │ 2024-06-17 05:00:00 │ 148 | │ 2024-06-24 05:00:00 │ 149 | └─────────────────────┘ 150 | ``` 151 | 152 | ## Function Documentation 153 | 154 | ### `cron(VARCHAR, start=TIMESTAMP, until=TIMESTAMP, timezone=VARCHAR)` 155 | 156 | #### Parameters: 157 | 158 | * `pattern` (VARCHAR): The cron pattern to evaluate. 159 | 160 | #### Optional Named Parameters: 161 | 162 | * `start` (TIMESTAMP): The timestamp at which to begin evaluating the cron pattern. 163 | * `until` (TIMESTAMP): The timestamp at which to stop evaluating the cron pattern (exclusive). 164 | * `timezone` (VARCHAR): The time zone in which to evaluate the cron pattern (e.g., 'America/New_York', 'America/Chicago'). 165 | 166 | #### Returning 167 | 168 | A single column `cron`, which contains timestamps when the cron pattern is satisfied. 169 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | use duckdb::{ 2 | vtab::{BindInfo, DataChunk, Free, FunctionInfo, InitInfo, LogicalType, LogicalTypeId, VTab}, 3 | Connection, Result, 4 | }; 5 | 6 | use chrono::{DateTime, Local, Utc}; 7 | use chrono_tz::Tz; 8 | use croner::Cron; 9 | use duckdb_loadable_macros::duckdb_entrypoint; 10 | use ffi::duckdb_vector_size; 11 | use libduckdb_sys as ffi; 12 | use std::{ 13 | error::Error, 14 | ffi::{c_char, c_void}, 15 | ptr::null_mut, 16 | }; 17 | 18 | #[repr(C)] 19 | struct CronBindData { 20 | // The cron expression. 21 | pattern: *mut Cron, 22 | start: DateTime, 23 | until: DateTime, 24 | timezone: Tz, 25 | } 26 | 27 | impl Free for CronBindData { 28 | fn free(&mut self) { 29 | unsafe { 30 | if self.pattern.is_null() { 31 | return; 32 | } 33 | drop(Box::from_raw(self.pattern)); 34 | } 35 | } 36 | } 37 | 38 | #[repr(C)] 39 | struct CronInitData { 40 | done: bool, 41 | } 42 | 43 | struct CronVTab; 44 | 45 | impl Free for CronInitData {} 46 | 47 | impl VTab for CronVTab { 48 | type InitData = CronInitData; 49 | type BindData = CronBindData; 50 | 51 | unsafe fn bind( 52 | bind: &BindInfo, 53 | data: *mut CronBindData, 54 | ) -> Result<(), Box> { 55 | bind.add_result_column("cron", LogicalType::new(LogicalTypeId::TimestampS)); 56 | 57 | let pattern = bind.get_parameter(0).to_string(); 58 | 59 | match Cron::new(&pattern) 60 | .with_seconds_optional() 61 | .with_dom_and_dow() 62 | .parse() 63 | { 64 | Ok(pattern) => { 65 | (*data).pattern = Box::into_raw(Box::new(pattern)); 66 | } 67 | Err(err) => { 68 | let error = format!("Failed to parse cron expression: {}", err); 69 | (*data).pattern = null_mut(); 70 | bind.set_error(&error); 71 | } 72 | } 73 | let utc_time: Tz = "UTC".parse().expect("UTC is an expected time zone"); 74 | 75 | (*data).timezone = match bind.get_named_parameter("timezone") { 76 | Some(timezone) => timezone.to_string().parse().unwrap_or_else(|_| { 77 | bind.set_error("Invalid or unknown time zone"); 78 | utc_time 79 | }), 80 | None => utc_time, 81 | }; 82 | 83 | let now: DateTime = Local::now().with_timezone(&(*data).timezone); 84 | let now_utc: DateTime = Local::now().into(); 85 | // This isn't getting the proper value, so I'm a big confused. 86 | (*data).start = match bind.get_named_parameter("start") { 87 | Some(value) => DateTime::from_timestamp(value.to_int64_timestamp() / 1000000, 0) 88 | .unwrap_or_else(|| { 89 | bind.set_error("Invalid starting time"); 90 | now_utc 91 | }) 92 | .with_timezone(&(*data).timezone), 93 | None => now, 94 | }; 95 | 96 | (*data).until = match bind.get_named_parameter("until") { 97 | Some(value) => DateTime::from_timestamp(value.to_int64_timestamp() / 1000000, 0) 98 | .unwrap_or_else(|| { 99 | bind.set_error("Invalid until time"); 100 | now_utc 101 | }) 102 | .with_timezone(&(*data).timezone), 103 | None => now, 104 | }; 105 | 106 | Ok(()) 107 | } 108 | 109 | unsafe fn init( 110 | _: &InitInfo, 111 | data: *mut CronInitData, 112 | ) -> Result<(), Box> { 113 | unsafe { 114 | (*data).done = false; 115 | } 116 | Ok(()) 117 | } 118 | 119 | unsafe fn func( 120 | func: &FunctionInfo, 121 | output: &mut DataChunk, 122 | ) -> Result<(), Box> { 123 | let init_info = func.get_init_data::(); 124 | let bind_info = func.get_bind_data::(); 125 | 126 | unsafe { 127 | let mut vector = output.flat_vector(0); 128 | 129 | if (*init_info).done { 130 | output.set_len(0) 131 | } else { 132 | // DuckDB has a limit to its vector size, respect it. 133 | let max_items: usize = duckdb_vector_size().try_into().unwrap(); 134 | let mut item_count: usize = 0; 135 | 136 | let timestamps: Vec = (*(*bind_info).pattern) 137 | .iter_from((*bind_info).start) 138 | .take_while(|&x| { 139 | if ((*bind_info).start == (*bind_info).until && item_count == 0) 140 | || (x <= (*bind_info).until && item_count < max_items) 141 | { 142 | item_count += 1; 143 | (*bind_info).start = x; 144 | true 145 | } else { 146 | false 147 | } 148 | }) 149 | .map(|x| x.timestamp()) 150 | .collect::>(); 151 | 152 | output.set_len(timestamps.len()); 153 | 154 | vector.copy(×tamps); 155 | 156 | // If the number of timestamps produced is less than the max_items 157 | // it means that the until limit has been reached. 158 | (*init_info).done = timestamps.len() < max_items; 159 | } 160 | } 161 | Ok(()) 162 | } 163 | 164 | fn parameters() -> Option> { 165 | // This is the single parameter which is the cron pattern. 166 | Some(vec![LogicalType::new(LogicalTypeId::Varchar)]) 167 | } 168 | 169 | fn named_parameters() -> Option> { 170 | Some(vec![ 171 | ( 172 | "start".to_string(), 173 | LogicalType::new(LogicalTypeId::Timestamp), 174 | ), 175 | ( 176 | "until".to_string(), 177 | LogicalType::new(LogicalTypeId::Timestamp), 178 | ), 179 | ( 180 | "timezone".to_string(), 181 | LogicalType::new(LogicalTypeId::Varchar), 182 | ), 183 | ]) 184 | } 185 | } 186 | 187 | // Exposes a extern C function named "libcrontab_init" in the compiled dynamic library, 188 | // the "entrypoint" that duckdb will use to load the extension. 189 | #[duckdb_entrypoint] 190 | pub fn libcrontab_init(conn: Connection) -> Result<(), Box> { 191 | conn.register_table_function::("cron")?; 192 | 193 | Ok(()) 194 | } 195 | --------------------------------------------------------------------------------