From 736e6f7abe8158fabd8d3e924c0ec9916e913db0 Mon Sep 17 00:00:00 2001 From: wudidapaopao Date: Wed, 2 Jul 2025 17:38:57 +0800 Subject: [PATCH] chore: support delta lake on linux x86-64 platform --- .../workflows/build_linux_arm64_wheels-gh.yml | 1 - .github/workflows/build_linux_x86_wheels.yml | 1 - .github/workflows/build_macos_x86_wheels.yml | 1 - chdb/build.sh | 15 +- rust/CMakeLists.txt | 2 + rust/README.md | 3 + rust/VENDOR.md | 65 + rust/chcache/.gitignore | 1 + rust/chcache/CMakeLists.txt | 18 + rust/chcache/Cargo.lock | 1449 ++++++++++++++ rust/chcache/Cargo.toml | 21 + rust/chcache/README.md | 0 rust/chcache/src/compilers/clang.rs | 323 +++ rust/chcache/src/compilers/mod.rs | 2 + rust/chcache/src/compilers/rustc.rs | 259 +++ rust/chcache/src/config.rs | 81 + rust/chcache/src/disks/clickhouse.rs | 82 + rust/chcache/src/disks/local.rs | 53 + rust/chcache/src/disks/mod.rs | 2 + rust/chcache/src/main.rs | 166 ++ rust/chcache/src/traits/compiler.rs | 15 + rust/chcache/src/traits/disk.rs | 9 + rust/chcache/src/traits/mod.rs | 2 + rust/copy_exclude.cmake | 2 - rust/workspace/CMakeLists.txt | 26 + rust/workspace/Cargo.lock | 1733 +++++++++++++++++ rust/workspace/Cargo.toml | 11 + rust/workspace/prql/Cargo.toml | 12 + rust/workspace/prql/include/prql.h | 18 + rust/workspace/prql/src/lib.rs | 109 ++ rust/workspace/skim/.gitignore | 2 + rust/workspace/skim/Cargo.toml | 18 + rust/workspace/skim/build.rs | 4 + rust/workspace/skim/include/skim.h | 90 + rust/workspace/skim/src/lib.rs | 113 ++ tests/test_delta_lake.py | 32 + 36 files changed, 4735 insertions(+), 6 deletions(-) create mode 100644 rust/CMakeLists.txt create mode 100644 rust/README.md create mode 100644 rust/VENDOR.md create mode 100644 rust/chcache/.gitignore create mode 100644 rust/chcache/CMakeLists.txt create mode 100644 rust/chcache/Cargo.lock create mode 100644 rust/chcache/Cargo.toml create mode 100644 rust/chcache/README.md create mode 100644 rust/chcache/src/compilers/clang.rs create mode 100644 rust/chcache/src/compilers/mod.rs create mode 100644 rust/chcache/src/compilers/rustc.rs create mode 100644 rust/chcache/src/config.rs create mode 100644 rust/chcache/src/disks/clickhouse.rs create mode 100644 rust/chcache/src/disks/local.rs create mode 100644 rust/chcache/src/disks/mod.rs create mode 100644 rust/chcache/src/main.rs create mode 100644 rust/chcache/src/traits/compiler.rs create mode 100644 rust/chcache/src/traits/disk.rs create mode 100644 rust/chcache/src/traits/mod.rs delete mode 100644 rust/copy_exclude.cmake create mode 100644 rust/workspace/CMakeLists.txt create mode 100644 rust/workspace/Cargo.lock create mode 100644 rust/workspace/Cargo.toml create mode 100644 rust/workspace/prql/Cargo.toml create mode 100644 rust/workspace/prql/include/prql.h create mode 100644 rust/workspace/prql/src/lib.rs create mode 100644 rust/workspace/skim/.gitignore create mode 100644 rust/workspace/skim/Cargo.toml create mode 100644 rust/workspace/skim/build.rs create mode 100644 rust/workspace/skim/include/skim.h create mode 100644 rust/workspace/skim/src/lib.rs create mode 100644 tests/test_delta_lake.py diff --git a/.github/workflows/build_linux_arm64_wheels-gh.yml b/.github/workflows/build_linux_arm64_wheels-gh.yml index 53f58542d33..4149989cc16 100644 --- a/.github/workflows/build_linux_arm64_wheels-gh.yml +++ b/.github/workflows/build_linux_arm64_wheels-gh.yml @@ -158,4 +158,3 @@ jobs: env: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} - diff --git a/.github/workflows/build_linux_x86_wheels.yml b/.github/workflows/build_linux_x86_wheels.yml index 2fd09ccb835..4a10ab2aa69 100644 --- a/.github/workflows/build_linux_x86_wheels.yml +++ b/.github/workflows/build_linux_x86_wheels.yml @@ -29,7 +29,6 @@ jobs: matrix: os: [ ubuntu-22.04 ] python-version: [ "3.8", "3.9", "3.10", "3.11", "3.12", "3.13" ] - # python-version: [ "3.7" ] env: RUNNER_OS: ${{ matrix.os }} PYTHON_VERSION: ${{ matrix.python-version }} diff --git a/.github/workflows/build_macos_x86_wheels.yml b/.github/workflows/build_macos_x86_wheels.yml index e76655a97cb..4663648cdcf 100644 --- a/.github/workflows/build_macos_x86_wheels.yml +++ b/.github/workflows/build_macos_x86_wheels.yml @@ -163,4 +163,3 @@ jobs: env: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} - diff --git a/chdb/build.sh b/chdb/build.sh index 853d67542d3..434296b2cd1 100755 --- a/chdb/build.sh +++ b/chdb/build.sh @@ -13,6 +13,7 @@ BUILD_DIR=${PROJ_DIR}/buildlib HDFS="-DENABLE_HDFS=1 -DENABLE_GSASL_LIBRARY=1 -DENABLE_KRB5=1" MYSQL="-DENABLE_MYSQL=1" +RUST_FEATURES="-DENABLE_RUST=0" # check current os type if [ "$(uname)" == "Darwin" ]; then export CXX=$(brew --prefix llvm@19)/bin/clang++ @@ -60,6 +61,18 @@ elif [ "$(uname)" == "Linux" ]; then if [ "$(uname -m)" == "x86_64" ]; then CPU_FEATURES="-DENABLE_AVX=1 -DENABLE_AVX2=0" LLVM="-DENABLE_EMBEDDED_COMPILER=1 -DENABLE_DWARF_PARSER=1" + RUST_FEATURES="-DENABLE_RUST=1 -DENABLE_DELTA_KERNEL_RS=1" + CORROSION_CMAKE_FILE="${PROJ_DIR}/contrib/corrosion-cmake/CMakeLists.txt" + if [ -f "${CORROSION_CMAKE_FILE}" ]; then + if ! grep -q 'OPENSSL_NO_DEPRECATED_3_0' "${CORROSION_CMAKE_FILE}"; then + echo "Modifying corrosion CMakeLists.txt for Linux x86_64..." + ${SED_INPLACE} 's/corrosion_set_env_vars(${target_name} "RUSTFLAGS=${RUSTFLAGS}")/corrosion_set_env_vars(${target_name} "RUSTFLAGS=${RUSTFLAGS} --cfg osslconf=\\\"OPENSSL_NO_DEPRECATED_3_0\\\"")/g' "${CORROSION_CMAKE_FILE}" + else + echo "corrosion CMakeLists.txt already modified, skipping..." + fi + else + echo "Warning: corrosion CMakeLists.txt not found at ${CORROSION_CMAKE_FILE}" + fi else CPU_FEATURES="-DENABLE_AVX=0 -DENABLE_AVX2=0 -DNO_ARMV81_OR_HIGHER=1" LLVM="-DENABLE_EMBEDDED_COMPILER=0 -DENABLE_DWARF_PARSER=0" @@ -84,7 +97,7 @@ CMAKE_ARGS="-DCMAKE_BUILD_TYPE=${build_type} -DENABLE_THINLTO=0 -DENABLE_TESTS=0 -DENABLE_LDAP=0 \ ${MYSQL} \ ${HDFS} \ - -DENABLE_LIBRARIES=0 -DENABLE_RUST=0 \ + -DENABLE_LIBRARIES=0 ${RUST_FEATURES} \ ${GLIBC_COMPATIBILITY} \ -DENABLE_UTILS=0 ${LLVM} ${UNWIND} \ ${ICU} -DENABLE_UTF8PROC=1 ${JEMALLOC} \ diff --git a/rust/CMakeLists.txt b/rust/CMakeLists.txt new file mode 100644 index 00000000000..3555b727d24 --- /dev/null +++ b/rust/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory (workspace) +add_subdirectory (chcache) diff --git a/rust/README.md b/rust/README.md new file mode 100644 index 00000000000..af92ea1cec5 --- /dev/null +++ b/rust/README.md @@ -0,0 +1,3 @@ +Read more about the Rust integration in the blog: + +## https://clickhouse.com/blog/rust diff --git a/rust/VENDOR.md b/rust/VENDOR.md new file mode 100644 index 00000000000..8c7266ccae9 --- /dev/null +++ b/rust/VENDOR.md @@ -0,0 +1,65 @@ +As we have multiple projects we use a workspace to manage them (it's way simpler and leads to less issues). In order +to vendor all the dependencies we need to store both the registry and the packages themselves. + +Note that this includes the exact `std` dependencies for the rustc version used in CI (currently nightly-2024-12-01), +so you need to install `rustup component add rust-src` for the specific version. + +* First step: (Re)-generate the Cargo.lock file (run under `workspace/`). + +```bash +cargo generate-lockfile +``` + +* Generate the local registry: + +Note that we use both commands to vendor both registry and crates. No idea why both are necessary. + + * First we need to install the tool if you don't already have it: +```bash +cargo install --version 0.2.7 cargo-local-registry +``` + + * Now add the local packages: + +```bash +export CH_TOP_DIR=$(git rev-parse --show-toplevel) +export RUSTC_ROOT=$(rustc --print=sysroot) +# Currently delta-lake is built outside the workspace (TODO) +export DELTA_LAKE_DIR="$CH_TOP_DIR"/contrib/delta-kernel-rs + +# Clean the vendor repo +rm -rf "$CH_TOP_DIR"/contrib/rust_vendor/* + +cd "$CH_TOP_DIR"/rust/workspace +cargo local-registry --git --sync Cargo.lock "$CH_TOP_DIR"/contrib/rust_vendor + +# Now handle delta-lake +cd "$DELTA_LAKE_DIR" +cargo local-registry --no-delete --git --sync "$DELTA_LAKE_DIR/Cargo.lock" "$CH_TOP_DIR"/contrib/rust_vendor + +# Standard library deps +cp "$RUSTC_ROOT"/lib/rustlib/src/rust/library/Cargo.lock "$RUSTC_ROOT"/lib/rustlib/src/rust/library/std/ +cargo local-registry --no-delete --git --sync "$RUSTC_ROOT"/lib/rustlib/src/rust/library/std/Cargo.lock "$CH_TOP_DIR"/contrib/rust_vendor +cp "$RUSTC_ROOT"/lib/rustlib/src/rust/library/Cargo.lock "$RUSTC_ROOT"/lib/rustlib/src/rust/library/test/ +cargo local-registry --no-delete --git --sync "$RUSTC_ROOT"/lib/rustlib/src/rust/library/test/Cargo.lock "$CH_TOP_DIR"/contrib/rust_vendor + +# Now we vendor the modules themselves +cd "$CH_TOP_DIR"/rust/workspace +cargo vendor --no-delete --locked "$CH_TOP_DIR"/contrib/rust_vendor +cd "$DELTA_LAKE_DIR" +cargo vendor --no-delete --locked "$CH_TOP_DIR"/contrib/rust_vendor +cd "$RUSTC_ROOT"/lib/rustlib/src/rust/library/std/ +cargo vendor --no-delete "$CH_TOP_DIR"/contrib/rust_vendor +cd "$RUSTC_ROOT"/lib/rustlib/src/rust/library/test/ +cargo vendor --no-delete "$CH_TOP_DIR"/contrib/rust_vendor + +# Remove windows only dependencies (which are really heavy and we don't want in the repo) +rm -rf "$CH_TOP_DIR"/contrib/rust_vendor/winapi* "$CH_TOP_DIR"/contrib/rust_vendor/windows* + +# Cleanup the lock files we copied +rm "$RUSTC_ROOT"/lib/rustlib/src/rust/library/std/Cargo.lock "$RUSTC_ROOT"/lib/rustlib/src/rust/library/test/Cargo.lock +cd "$CH_TOP_DIR"/rust/workspace +``` + +The `rustc --print=sysroot` part includes `std` dependencies, required to build with sanitizer flags. It must be kept +in sync with the rustc version used in CI. diff --git a/rust/chcache/.gitignore b/rust/chcache/.gitignore new file mode 100644 index 00000000000..ea8c4bf7f35 --- /dev/null +++ b/rust/chcache/.gitignore @@ -0,0 +1 @@ +/target diff --git a/rust/chcache/CMakeLists.txt b/rust/chcache/CMakeLists.txt new file mode 100644 index 00000000000..86bfb8a7e1b --- /dev/null +++ b/rust/chcache/CMakeLists.txt @@ -0,0 +1,18 @@ +if (COMPILER_CACHE STREQUAL "chcache") + corrosion_import_crate( + MANIFEST_PATH Cargo.toml + PROFILE release + LOCKED + ) + + corrosion_set_env_vars( + chcache + RUSTFLAGS= + RUST_CFLAGS= + RUST_CXXFLAGS= + CFLAGS= + CXXFLAGS= + ) + + corrosion_set_hostbuild(chcache) +endif() diff --git a/rust/chcache/Cargo.lock b/rust/chcache/Cargo.lock new file mode 100644 index 00000000000..46a96579152 --- /dev/null +++ b/rust/chcache/Cargo.lock @@ -0,0 +1,1449 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets", +] + +[[package]] +name = "bitflags" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" + +[[package]] +name = "blake3" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389a099b34312839e16420d499a9cad9650541715937ffbdd40d36f49e77eeb3" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", +] + +[[package]] +name = "bstr" +version = "1.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "531a9155a481e2ee699d4f98f43c0ca4ff8ee1bfd55c31e9e98fb29d2b176fe0" +dependencies = [ + "memchr", +] + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" + +[[package]] +name = "cc" +version = "1.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chcache" +version = "1.0.0" +dependencies = [ + "blake3", + "clickhouse", + "env_logger", + "log", + "serde", + "serde_bytes", + "serde_json", + "tar", + "tokio", + "toml", + "xdg", +] + +[[package]] +name = "cityhash-rs" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93a719913643003b84bd13022b4b7e703c09342cd03b679c4641c7d2e50dc34d" + +[[package]] +name = "clickhouse" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9894248c4c5a4402f76a56c273836a0c32547ec8a68166aedee7e01b7b8d102" +dependencies = [ + "bstr", + "bytes", + "cityhash-rs", + "clickhouse-derive", + "futures", + "futures-channel", + "http-body-util", + "hyper", + "hyper-tls", + "hyper-util", + "lz4_flex", + "replace_with", + "sealed", + "serde", + "static_assertions", + "thiserror", + "tokio", + "url", +] + +[[package]] +name = "clickhouse-derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d70f3e2893f7d3e017eeacdc9a708fbc29a10488e3ebca21f9df6a5d2b616dbb" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn", +] + +[[package]] +name = "constant_time_eq" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "env_filter" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" +dependencies = [ + "log", +] + +[[package]] +name = "env_logger" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" +dependencies = [ + "env_filter", + "log", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "filetime" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" +dependencies = [ + "cfg-if", + "libc", + "libredox", + "windows-sys 0.59.0", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "getrandom" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" + +[[package]] +name = "http" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "hyper" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497bbc33a26fdd4af9ed9c70d63f61cf56a938375fbb32df34db9b1cd6d643f2" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "libc", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "indexmap" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "libc" +version = "0.2.171" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" + +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags", + "libc", + "redox_syscall", +] + +[[package]] +name = "linux-raw-sys" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe7db12097d22ec582439daf8618b8fdd1a7bef6270e9af3b1ebcd30893cf413" + +[[package]] +name = "litemap" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "lz4_flex" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75761162ae2b0e580d7e7c390558127e5f01b4194debd6221fd8c207fc80e3f5" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "miniz_oxide" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +dependencies = [ + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.52.0", +] + +[[package]] +name = "native-tls" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "openssl" +version = "0.10.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + +[[package]] +name = "openssl-sys" +version = "0.9.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8288979acd84749c744a9014b4382d42b8f7b2592847b5afb2ed29e5d16ede07" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "proc-macro2" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + +[[package]] +name = "redox_syscall" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" +dependencies = [ + "bitflags", +] + +[[package]] +name = "replace_with" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a8614ee435691de62bcffcf4a66d91b3594bf1428a5722e79103249a095690" + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustix" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.59.0", +] + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "schannel" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "sealed" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22f968c5ea23d555e670b449c1c5e7b2fc399fdaec1d304a17cd48e288abc107" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_bytes" +version = "0.11.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8437fd221bde2d4ca316d61b90e337e9e702b3820b87d63caa9ba6c02bd06d96" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_derive_internals" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.140" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" + +[[package]] +name = "socket2" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "syn" +version = "2.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[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.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" +dependencies = [ + "fastrand", + "getrandom", + "once_cell", + "rustix", + "windows-sys 0.52.0", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tokio" +version = "1.44.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a" +dependencies = [ + "backtrace", + "libc", + "mio", + "pin-project-lite", + "socket2", + "tokio-macros", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-macros" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "toml" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "url" +version = "2.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e97b544156e9bebe1a0ffbc03484fc1ffe3100cbce3ffb17eac35f7cdd7ab36" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags", +] + +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + +[[package]] +name = "xattr" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d65cbf2f12c15564212d48f4e3dfb87923d25d611f2aed18f4cb23f0413d89e" +dependencies = [ + "libc", + "rustix", +] + +[[package]] +name = "xdg" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546" + +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/rust/chcache/Cargo.toml b/rust/chcache/Cargo.toml new file mode 100644 index 00000000000..42da158936c --- /dev/null +++ b/rust/chcache/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "chcache" +version = "1.0.0" +edition = "2021" + +[dependencies] +blake3 = "1.5.4" +clickhouse = { version = "0.13.1", features = ["native-tls"] } +env_logger = { version = "0.11.5", default-features = false } +log = "0.4.22" +serde = { version = "1.0.215", features = ["serde_derive"] } +serde_bytes = "0.11.15" +serde_json = "1.0.140" +tar = "0.4.44" +tokio = { version = "1.42.0", features = ["rt-multi-thread"] } +toml = "0.8.19" +xdg = "2.5.2" + +[[bin]] +name = "chcache" +path = "src/main.rs" diff --git a/rust/chcache/README.md b/rust/chcache/README.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/rust/chcache/src/compilers/clang.rs b/rust/chcache/src/compilers/clang.rs new file mode 100644 index 00000000000..cb94e30a77b --- /dev/null +++ b/rust/chcache/src/compilers/clang.rs @@ -0,0 +1,323 @@ +use std::error::Error; +use std::fs; + +use blake3::Hasher; +use log::trace; + +use crate::traits::compiler::Compiler; +use crate::traits::compiler::CompilerMeta; + +pub struct ClangLike { + compiler_path: String, + + args: Vec, + stripped_args: Vec, + + input: String, + output: String, + + relative_output: String, +} + +impl ClangLike { + pub fn from_args(compiler_path: String, args: Vec) -> Self { + let cwd = std::env::current_dir() + .unwrap() + .into_os_string() + .into_string() + .unwrap() + .trim_end_matches('/') + .to_string(); + trace!("Current working directory: {}", cwd); + + let assumed_base_path = ClangLike::assume_base_path(&args); + + let stripped_args = args + .iter() + .map(|x| x.replace(&cwd, "/")) + .map(|x| x.replace(&assumed_base_path, "/")) + .collect::>(); + + ClangLike { + compiler_path, + + input: ClangLike::get_input_from_args(&args), + output: ClangLike::get_output_from_args(&args), + + relative_output: ClangLike::get_output_from_args(&stripped_args), + + args, + stripped_args, + } + } + + fn assume_base_path(args: &Vec) -> String { + let cwd: String = match std::env::current_dir() { + Ok(pathbuf) => pathbuf.into_os_string().into_string().unwrap(), + _ => { + panic!("Couldn't get current directory"); + } + }; + + let mut maybe_basepath: Vec = vec![cwd]; + + for (i, arg) in args.iter().enumerate() { + if arg.starts_with("-I") { + maybe_basepath.push(arg[2..].to_string()); + continue; + } + if arg == "-isystem" || arg == "-c" { + maybe_basepath.push(args[i + 1].to_string()); + continue; + } + if arg.starts_with("--gcc-toolchain") { + maybe_basepath.push(arg[16..].to_string()); + continue; + } + if arg.starts_with("--sysroot") { + maybe_basepath.push(arg[10..].to_string()); + continue; + } + } + + let maybe_basepaths_sep_by_slash: Vec> = maybe_basepath + .into_iter() + .map(|x| x.split("/").map(|x| x.to_string()).collect()) + .collect(); + let mut basepath = "".to_string(); + + for i in 0..maybe_basepaths_sep_by_slash[0].len() { + for j in 1..maybe_basepaths_sep_by_slash.len() { + if maybe_basepaths_sep_by_slash[0][i] != maybe_basepaths_sep_by_slash[j][i] { + return basepath.trim_end_matches('/').to_string(); + } + } + basepath.push_str(&maybe_basepaths_sep_by_slash[0][i]); + basepath.push_str("/"); + } + + basepath.trim_end_matches('/').to_string() + } + + pub fn compiler_version(compiler_path: String) -> String { + trace!("Using compiler: {}", compiler_path); + + let compiler_version = std::process::Command::new(compiler_path.clone()) + .arg("-dM") + .arg("-E") + .arg("-x") + .arg("c") + .arg("/dev/null") + .output() + .expect("Failed to execute command"); + + let compiler_version = String::from_utf8_lossy(&compiler_version.stdout); + + let compiler_version = compiler_version + .lines() + .find(|x| x.starts_with("#define __VERSION__")) + .unwrap() + .split_whitespace() + .skip(2) + .collect::>() + .join(" "); + + compiler_version.trim_matches('"').to_string() + } + + fn get_output_from_args(args: &Vec) -> String { + let mut target = String::new(); + for (i, arg) in args.iter().enumerate() { + if arg == "-o" { + target = args[i + 1].to_string(); + break; + } + } + target + } + + fn get_input_from_args(args: &Vec) -> String { + let mut target = String::new(); + for (i, arg) in args.iter().enumerate() { + if arg == "-c" { + target = args[i + 1].to_string(); + break; + } + } + target + } + + fn hash_compiler_target(&self) -> String { + let mut hasher = Hasher::new(); + + let data = fs::read(&self.input).expect("Unable to read file"); + hasher.update(&data); + hasher.update(&self.relative_output.as_bytes()); + + hasher.finalize().to_hex().to_string() + } + + fn hash_preprocessed_compiler_output(&self) -> String { + let mut preprocess_args = vec![ + "-E".to_string(), + "-P".to_string(), + "-fminimize-whitespace".to_string(), + ]; + preprocess_args.extend(self.args.clone()); + + let output_flag_index = preprocess_args.iter().position(|x| x == "-o").unwrap(); + preprocess_args.remove(output_flag_index); + preprocess_args.remove(output_flag_index); + + let input_flag_index = preprocess_args.iter().position(|x| x == "-c").unwrap(); + preprocess_args.remove(input_flag_index); + + let output = std::process::Command::new(self.compiler_path.clone()) + .args(preprocess_args) + .output() + .expect("Failed to execute command"); + + let stdout_output = String::from_utf8_lossy(&output.stdout); + let stderr_output = String::from_utf8_lossy(&output.stderr); + + if stdout_output.is_empty() { + panic!("{}", stderr_output); + } + + let mut hasher = Hasher::new(); + hasher.update(stdout_output.as_bytes()); + + hasher.finalize().to_hex().to_string() + } +} + +impl CompilerMeta for Clang { + const NAME: &'static str = "clang"; + + fn from_args(compiler_path: String, args: Vec) -> Box { + assert!(compiler_path.ends_with(Clang::NAME)); + + Box::new(Clang(ClangLike::from_args(compiler_path, args))) + } +} + +impl CompilerMeta for ClangXX { + const NAME: &'static str = "clang++"; + + fn from_args(compiler_path: String, args: Vec) -> Box { + assert!(compiler_path.ends_with(ClangXX::NAME)); + + Box::new(ClangXX(ClangLike::from_args(compiler_path, args))) + } +} + +impl Compiler for ClangLike { + fn compile(&self) -> Result, Box> { + let output = std::process::Command::new(self.compiler_path.clone()) + .args(&self.args) + .output() + .unwrap(); + + if !output.status.success() { + println!("{}", String::from_utf8_lossy(&output.stdout)); + eprintln!("{}", String::from_utf8_lossy(&output.stderr)); + std::process::exit(output.status.code().unwrap_or(1)); + } + + Ok(fs::read(&self.output)?) + } + + fn version(&self) -> String { + ClangLike::compiler_version(self.compiler_path.clone()) + } + + fn cache_key(&self) -> String { + let mut hasher = Hasher::new(); + + self.stripped_args + .iter() + .map(|x| x.as_bytes()) + .for_each(|x| { + hasher.update(x); + }); + + let args_hash = hasher.finalize().to_string(); + + let compiler_version = self.version(); + + trace!("Compiler version: {}", compiler_version); + + let compiler_target_hash = ClangLike::hash_compiler_target(&self); + let preprocessed_output_hash = self.hash_preprocessed_compiler_output(); + + trace!("Compiler target hash: {}", compiler_target_hash); + trace!("Preprocessed output hash: {}", preprocessed_output_hash); + trace!("Args hash: {}", args_hash); + + hasher.reset(); + + hasher.update(compiler_version.as_bytes()); + hasher.update(compiler_target_hash.as_bytes()); + hasher.update(preprocessed_output_hash.as_bytes()); + hasher.update(args_hash.as_bytes()); + + hasher.finalize().to_string() + } + + fn apply_cache(&self, binary: &Vec) -> Result<(), Box> { + fs::write(&self.relative_output, binary)?; + + Ok(()) + } + + fn cacheable(&self) -> bool { + true + } +} + +pub struct Clang(ClangLike); +pub struct ClangXX(ClangLike); + +impl Compiler for ClangXX { + fn compile(&self) -> Result, Box> { + self.0.compile() + } + + fn cache_key(&self) -> String { + self.0.cache_key() + } + + fn apply_cache(&self, binary: &Vec) -> Result<(), Box> { + self.0.apply_cache(binary) + } + + fn cacheable(&self) -> bool { + self.0.cacheable() + } + + fn version(&self) -> String { + self.0.version() + } +} + +impl Compiler for Clang { + fn compile(&self) -> Result, Box> { + self.0.compile() + } + + fn cache_key(&self) -> String { + self.0.cache_key() + } + + fn apply_cache(&self, binary: &Vec) -> Result<(), Box> { + self.0.apply_cache(binary) + } + + fn cacheable(&self) -> bool { + self.0.cacheable() + } + + fn version(&self) -> String { + self.0.version() + } +} diff --git a/rust/chcache/src/compilers/mod.rs b/rust/chcache/src/compilers/mod.rs new file mode 100644 index 00000000000..4833a2d439c --- /dev/null +++ b/rust/chcache/src/compilers/mod.rs @@ -0,0 +1,2 @@ +pub mod rustc; +pub mod clang; diff --git a/rust/chcache/src/compilers/rustc.rs b/rust/chcache/src/compilers/rustc.rs new file mode 100644 index 00000000000..e02669c33e0 --- /dev/null +++ b/rust/chcache/src/compilers/rustc.rs @@ -0,0 +1,259 @@ +use blake3::Hasher; +use log::trace; +use std::error::Error; +use std::fs::{self}; +use std::io::Cursor; +use std::path::Path; + +use crate::{ + compilers::clang::ClangLike, + traits::compiler::{Compiler, CompilerMeta}, +}; + +pub struct RustC { + compiler_path: String, + + args: Vec, + out_dir: String, +} + +impl CompilerMeta for RustC { + const NAME: &'static str = "rustc"; + + fn from_args(compiler_path: String, args: Vec) -> Box { + let out_dir = args + .iter() + .position(|x| x == "--out-dir") + .map(|x| args[x + 1].clone()) + .unwrap_or(String::new()); + + Box::new(RustC { + compiler_path, + args, + out_dir, + }) + } +} + +impl Compiler for RustC { + fn cache_key(&self) -> String { + let mut maybe_basepath: Vec = vec![]; + + for (i, arg) in self.args.iter().enumerate() { + if arg.starts_with("--out-dir") { + maybe_basepath.push(self.args[i + 1].to_string()); + continue; + } + if arg == "-C" || arg == "-L" { + let next = self.args[i + 1].to_string(); + + if next.starts_with("path=") { + maybe_basepath.push(next[5..].to_string()); + continue; + } + + if next.starts_with("dependency=") { + maybe_basepath.push(next[11..].to_string()); + continue; + } + + if next.starts_with("native=") { + maybe_basepath.push(next[7..].to_string()); + continue; + } + + continue; + } + } + + trace!("Maybe basepath: {:?}", maybe_basepath); + + let maybe_basepaths_sep_by_slash: Vec> = maybe_basepath + .into_iter() + .map(|x| x.split("/").map(|x| x.to_string()).collect()) + .collect(); + let mut basepath = "".to_string(); + + 'outer: for i in 0..maybe_basepaths_sep_by_slash[0].len() { + for j in 1..maybe_basepaths_sep_by_slash.len() { + if maybe_basepaths_sep_by_slash[0][i] != maybe_basepaths_sep_by_slash[j][i] { + basepath = basepath.trim_end_matches('/').to_string(); + + break 'outer; + } + } + + basepath.push_str(&maybe_basepaths_sep_by_slash[0][i]); + basepath.push_str("/"); + } + + basepath = basepath.trim_end_matches('/').to_string(); + trace!("Basepath: {:?}", basepath); + assert!(!basepath.is_empty()); + assert!(!basepath.ends_with('/')); + + let cargo_manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); + assert!(!cargo_manifest_dir.is_empty()); + + let cargo_manifest_dir = std::path::Path::new(&cargo_manifest_dir); + + let mut stripped_args = self + .args + .clone() + .iter() + .map(|x| { + if x.ends_with(".rs") { + let path = std::path::Path::new(x); + let stripped = { + let mut p_iter = cargo_manifest_dir.components(); + let mut x_iter = path.components(); + + while let (Some(p), Some(xp)) = (p_iter.next(), x_iter.next()) { + if p != xp { + break; + } + } + + x_iter.as_path() + }; + trace!("Stripped path: {:?}", stripped); + stripped.to_string_lossy().into_owned() + } else { + x.replace(&basepath, "./") + } + }) + .collect::>(); + + if let Some(index) = stripped_args.iter().position(|x| x == "--out-dir") { + stripped_args.remove(index); + stripped_args.remove(index); + } + + if let Some(index) = stripped_args + .iter() + .position(|x| x.starts_with("--diagnostic-width")) + { + stripped_args.remove(index); + } + + // May have different linkers between developers. + // - "-C", "linker=/src/llvm/llvm-project/.cmake/bin/clang", + // + "-C", "linker=/usr/bin/clang", + let mut clang_linker_version: Option = None; + if let Some(index) = stripped_args.iter().position(|x| x.contains("linker=")) { + let linker = stripped_args[index].replace("linker=", ""); + assert!(!linker.is_empty()); + assert!(linker.ends_with("clang")); + + clang_linker_version = Some(ClangLike::compiler_version(linker)); + stripped_args.remove(index); + } + + trace!("Stripped args: {:?}", stripped_args); + + let mut hasher = Hasher::new(); + + stripped_args.iter().map(|x| x.as_bytes()).for_each(|x| { + hasher.update(&x); + }); + hasher.update(std::env::var("CARGO_PKG_NAME").unwrap().as_bytes()); + if clang_linker_version.is_some() { + hasher.update(clang_linker_version.unwrap().as_bytes()); + } + + hasher.finalize().to_string() + } + + fn version(&self) -> String { + trace!("Using compiler: {}", self.compiler_path); + + let compiler_version = std::process::Command::new(self.compiler_path.clone()) + .arg("-V") + .output() + .expect("Failed to execute command"); + + String::from_utf8_lossy(&compiler_version.stdout).to_string() + } + + fn cacheable(&self) -> bool { + if self.out_dir.is_empty() { + return false; + } + + if self.args.iter().any(|arg| { + arg == "--version" + || arg == "--help" + || arg == "--explain" + || arg == "-vV" + || arg == "--print" + }) { + return false; + } + + let has_input = self.args.iter().any(|arg| arg.ends_with(".rs")); + if !has_input { + return false; + } + + if self.args.iter().any(|arg| arg.contains("emit=link")) { + return false; + } + + true + } + + fn apply_cache(&self, bytes: &Vec) -> Result<(), Box> { + trace!("Out dir: {:?}", self.out_dir); + + let cursor = Cursor::new(bytes); + let mut archive = tar::Archive::new(cursor); + archive.set_preserve_mtime(false); + archive.unpack(&self.out_dir)?; + + Ok(()) + } + + fn compile(&self) -> Result, Box> { + let output = std::process::Command::new(self.compiler_path.clone()) + .args(&self.args) + .output() + .unwrap(); + + if !output.status.success() { + println!("{}", String::from_utf8_lossy(&output.stdout)); + eprintln!("{}", String::from_utf8_lossy(&output.stderr)); + std::process::exit(output.status.code().unwrap_or(1)); + } + + let files_to_pack = String::from_utf8_lossy(&output.stderr); + let files_to_pack = files_to_pack + .lines() + .filter(|line| line.starts_with("{\"$message_type\":\"artifact\"")) + .map(|x| { + let json: serde_json::Value = serde_json::from_str(x).unwrap(); + let artifact = json["artifact"].as_str().unwrap(); + let artifact = artifact.replace("\"", ""); + artifact + }) + .collect::>(); + + trace!("Files to pack: {:?}", files_to_pack); + + let mut buffer = Vec::new(); + let cursor = Cursor::new(&mut buffer); + let mut archive = tar::Builder::new(cursor); + for file in &files_to_pack { + let file = Path::new(&file); + let filename = file.strip_prefix(&self.out_dir).unwrap(); + let filename = filename.to_str().unwrap(); + trace!("Packing file: {}", file.display()); + let mut packed_file = fs::File::open(file).unwrap(); + archive.append_file(filename, &mut packed_file).unwrap(); + } + + archive.finish().unwrap(); + drop(archive); + + Ok(buffer) + } +} diff --git a/rust/chcache/src/config.rs b/rust/chcache/src/config.rs new file mode 100644 index 00000000000..cde0a155d2e --- /dev/null +++ b/rust/chcache/src/config.rs @@ -0,0 +1,81 @@ +use log::trace; +use std::fs; + +#[derive(Debug, serde::Deserialize)] +#[serde(default)] +pub struct Config { + pub hostname: String, + pub user: String, + pub password: String, + + pub source_table: String, + pub target_table: String, +} + +impl Default for Config { + fn default() -> Self { + Config { + hostname: "https://build-cache.eu-west-1.aws.clickhouse-staging.com".to_string(), + user: "reader".to_string(), + password: "reader".to_string(), + + source_table: "default.build_cache".to_string(), + target_table: "default.build_cache".to_string(), + } + } +} + +impl Config { + pub fn init() -> Self { + let config_path = xdg::BaseDirectories::with_prefix("chcache") + .unwrap() + .place_config_file("config.toml") + .unwrap(); + + let mut env_vars_available = true; + let required_env_vars = vec!["CH_HOSTNAME", "CH_USER", "CH_PASSWORD"]; + for var in required_env_vars { + if std::env::var(var).is_ok() { + continue; + } + + env_vars_available = false; + break; + } + + let config: Config = match (config_path.exists(), env_vars_available) { + (true, _) => { + trace!( + "Loading config file contents from {}", + config_path.display() + ); + + let config_text = fs::read_to_string(config_path).expect("Missing config file?"); + toml::from_str(&config_text).expect("Unable to load config, is it a valid toml?") + } + (_, true) => { + trace!( + "Config file not found at {}, trying env vars", + config_path.display() + ); + + Config { + hostname: std::env::var("CH_HOSTNAME").unwrap(), + user: std::env::var("CH_USER").unwrap(), + password: std::env::var("CH_PASSWORD").unwrap(), + + ..Default::default() + } + } + (false, false) => { + trace!( + "Config file not found at {}, and env vars are missing, using defaults", + config_path.display() + ); + Config::default() + } + }; + + config + } +} diff --git a/rust/chcache/src/disks/clickhouse.rs b/rust/chcache/src/disks/clickhouse.rs new file mode 100644 index 00000000000..cbcf165ee71 --- /dev/null +++ b/rust/chcache/src/disks/clickhouse.rs @@ -0,0 +1,82 @@ +use std::error::Error; + +use crate::config::Config; +use crate::traits::disk::Disk; + +pub struct ClickHouseDisk { + client: clickhouse::Client, + + source_table: String, + target_table: String, +} + +#[derive(Debug, clickhouse::Row, serde::Serialize, serde::Deserialize)] +struct CacheLine { + #[serde(with = "serde_bytes")] + blob: Vec, + hash: String, + compiler_version: String, +} + +impl Disk for ClickHouseDisk { + fn from_config(config: &Config) -> Self { + let client = clickhouse::Client::default() + .with_url(&config.hostname) + .with_user(&config.user) + .with_password(&config.password) + .with_compression(clickhouse::Compression::Lz4) + .with_option("async_insert", "1") + .with_option("wait_for_async_insert", "0"); + + ClickHouseDisk { + client, + + source_table: config.source_table.clone(), + target_table: config.target_table.clone(), + } + } + + async fn read(&self, _hash: &str) -> Result, Box> { + unimplemented!() + } + + async fn write(&self, _hash: &str, _data: &Vec) -> Result<(), Box> { + unimplemented!() + } +} + +impl ClickHouseDisk { + pub async fn read(&self, compiler_version: &str, hash: &str) -> Result, Box> { + let query = format!( + "SELECT ?fields FROM {} WHERE hash = ? and compiler_version = ? LIMIT 1", + &self.source_table + ); + + let mut cursor = self + .client + .query(&query) + .bind(hash) + .bind(compiler_version) + .fetch::() + .unwrap(); + + while let Some(row) = cursor.next().await? { + return Ok(row.blob); + } + + Err("Cache miss".into()) + } + + pub async fn write(&self, compiler_version: &str, hash: &str, data: &Vec) -> Result<(), Box> { + let mut insert = self.client.insert(&self.target_table).unwrap(); + + let row = CacheLine { + blob: data.clone(), + hash: hash.to_string(), + compiler_version: compiler_version.to_string(), + }; + + insert.write(&row).await?; + insert.end().await.map_err(Into::into) + } +} diff --git a/rust/chcache/src/disks/local.rs b/rust/chcache/src/disks/local.rs new file mode 100644 index 00000000000..58b8e598e87 --- /dev/null +++ b/rust/chcache/src/disks/local.rs @@ -0,0 +1,53 @@ +use log::trace; +use std::error::Error; +use std::fs; +use xdg::BaseDirectories; + +use crate::config::Config; +use crate::traits::disk::Disk; + +pub struct LocalDisk { + local_path: BaseDirectories, +} + +impl Disk for LocalDisk { + fn from_config(_config: &Config) -> Self { + let local_path = xdg::BaseDirectories::with_prefix("chcache").unwrap(); + LocalDisk { local_path } + } + + async fn read(&self, hash: &str) -> Result, Box> { + let cache_file = self + .local_path + .get_cache_file(LocalDisk::path_from_hash(&hash)); + trace!("Reading cache file: {:?}", cache_file); + + let data = fs::read(cache_file)?; + return Ok(data); + } + + async fn write(&self, hash: &str, data: &Vec) -> Result<(), Box> { + let cache_file = self + .local_path + .place_cache_file(LocalDisk::path_from_hash(&hash))?; + trace!("Writing cache file: {:?}", cache_file); + + let cache_file_dir = cache_file.parent().unwrap(); + + fs::create_dir_all(cache_file_dir)?; + fs::write(cache_file, data)?; + + Ok(()) + } +} + +impl LocalDisk { + fn path_from_hash(hash: &str) -> String { + return format!( + "{}/{}/{}", + hash.get(0..2).unwrap(), + hash.get(2..4).unwrap(), + hash + ); + } +} diff --git a/rust/chcache/src/disks/mod.rs b/rust/chcache/src/disks/mod.rs new file mode 100644 index 00000000000..abd3eb6593d --- /dev/null +++ b/rust/chcache/src/disks/mod.rs @@ -0,0 +1,2 @@ +pub mod local; +pub mod clickhouse; diff --git a/rust/chcache/src/main.rs b/rust/chcache/src/main.rs new file mode 100644 index 00000000000..9b3727621ba --- /dev/null +++ b/rust/chcache/src/main.rs @@ -0,0 +1,166 @@ +use log::{error, info, trace, warn}; +use std::error::Error; + +mod compilers; +mod config; +mod disks; +mod traits; + +use crate::compilers::clang::{Clang, ClangXX}; +use crate::compilers::rustc::RustC; +use crate::config::Config; +use crate::disks::clickhouse::ClickHouseDisk; +use crate::disks::local::LocalDisk; +use crate::traits::compiler::CompilerMeta; +use crate::traits::disk::Disk; + +#[tokio::main] +async fn main() -> Result<(), Box> { + env_logger::init(); + + compiler_cache_entrypoint(&Config::init()).await +} + +async fn compiler_cache_entrypoint(config: &Config) -> Result<(), Box> { + let compiler_path: String = std::env::args().nth(1).unwrap(); + let rest_of_args: Vec = std::env::args().skip(2).collect(); + + trace!("Compiler: {}", compiler_path); + trace!("Args: {:?}", rest_of_args); + + let just_compiler_name = compiler_path + .split('/') + .last() + .unwrap_or(&compiler_path) + .to_string(); + + let compiler = match just_compiler_name.as_str() { + RustC::NAME => RustC::from_args( + compiler_path.clone(), + rest_of_args.clone(), + ), + Clang::NAME => Clang::from_args( + compiler_path.clone(), + rest_of_args.clone(), + ), + ClangXX::NAME => ClangXX::from_args( + compiler_path.clone(), + rest_of_args.clone(), + ), + _ => { + panic!("Unknown compiler: {}", compiler_path); + } + }; + + if !compiler.cacheable() { + trace!("Call is not cacheable"); + + let output = std::process::Command::new(compiler_path) + .args(&rest_of_args) + .output() + .unwrap(); + + let stdout = String::from_utf8_lossy(&output.stdout) + .lines() + .filter(|c| !c.is_empty()) + .collect::>() + .join("\n"); + + println!("{}", stdout); + eprintln!("{}", String::from_utf8_lossy(&output.stderr)); + if !output.status.success() { + std::process::exit(output.status.code().unwrap_or(1)); + } + + return Ok(()); + } + + let local_disk = LocalDisk::from_config(config); + let clickhouse_disk: ClickHouseDisk = ClickHouseDisk::from_config(config); + + let total_hash = compiler.cache_key(); + let compiler_version = compiler.version(); + + let mut did_load_from_local_cache = false; + let mut did_load_from_clickhouse = false; + + let compiled_bytes: Vec = match local_disk.read(&total_hash).await { + Ok(bytes) => { + info!("Local cache hit"); + + compiler + .apply_cache(&bytes) + .expect(&("Unable to apply local cache for hash ".to_owned() + &total_hash)); + did_load_from_local_cache = true; + + bytes + } + Err(e) => { + trace!("Got error: {:?}", e); + trace!("Cache miss"); + + let compiled_bytes = match clickhouse_disk.read(&compiler_version, &total_hash).await { + Ok(bytes) => { + info!("Loaded from ClickHouse"); + + compiler + .apply_cache(&bytes) + .expect("Unable to apply cache from ClickHouse"); + + did_load_from_clickhouse = true; + + bytes + } + Err(e) => { + trace!("Got error from CH: {:?}", e); + compiler.compile().expect("Unable to compile") + } + }; + + compiled_bytes + } + }; + + if !did_load_from_local_cache { + local_disk + .write(&total_hash, &compiled_bytes) + .await + .unwrap(); + } + + let should_upload = { + let default_config = Config::default(); + + !did_load_from_local_cache && !did_load_from_clickhouse && config.user != default_config.user + }; + + if should_upload { + let mut tries = 3; + loop { + let upload_result = clickhouse_disk + .write( + &compiler_version, + &total_hash, + &compiled_bytes, + ) + .await; + + if upload_result.is_ok() { + info!("Uploaded to ClickHouse"); + break; + } + warn!("Failed to upload to ClickHouse, retrying..."); + + tries -= 1; + if tries == 0 { + error!( + "Failed to upload to ClickHouse: {}", + upload_result.err().unwrap() + ); + break; + } + } + } + + Ok(()) +} diff --git a/rust/chcache/src/traits/compiler.rs b/rust/chcache/src/traits/compiler.rs new file mode 100644 index 00000000000..df498b25a0b --- /dev/null +++ b/rust/chcache/src/traits/compiler.rs @@ -0,0 +1,15 @@ +use std::error::Error; + +pub trait CompilerMeta { + const NAME: &'static str; + fn from_args(compiler_path: String, args: Vec) -> Box; +} + +pub trait Compiler { + fn cacheable(&self) -> bool; + fn cache_key(&self) -> String; + fn version(&self) -> String; + + fn compile(&self) -> Result, Box>; + fn apply_cache(&self, source: &Vec) -> Result<(), Box>; +} diff --git a/rust/chcache/src/traits/disk.rs b/rust/chcache/src/traits/disk.rs new file mode 100644 index 00000000000..56afd491571 --- /dev/null +++ b/rust/chcache/src/traits/disk.rs @@ -0,0 +1,9 @@ +use std::error::Error; +use crate::config::Config; + +pub trait Disk { + fn from_config(config: &Config) -> Self; + + async fn read(&self, hash: &str) -> Result, Box>; + async fn write(&self, hash: &str, data: &Vec) -> Result<(), Box>; +} diff --git a/rust/chcache/src/traits/mod.rs b/rust/chcache/src/traits/mod.rs new file mode 100644 index 00000000000..edfd4b28b5e --- /dev/null +++ b/rust/chcache/src/traits/mod.rs @@ -0,0 +1,2 @@ +pub mod compiler; +pub mod disk; diff --git a/rust/copy_exclude.cmake b/rust/copy_exclude.cmake deleted file mode 100644 index c6a6ff56b6e..00000000000 --- a/rust/copy_exclude.cmake +++ /dev/null @@ -1,2 +0,0 @@ -file(COPY "${FROM}" DESTINATION "${TO}" - PATTERN target EXCLUDE) diff --git a/rust/workspace/CMakeLists.txt b/rust/workspace/CMakeLists.txt new file mode 100644 index 00000000000..6c62281d82f --- /dev/null +++ b/rust/workspace/CMakeLists.txt @@ -0,0 +1,26 @@ +if (OS_FREEBSD) + # Right nix/libc requires fspacectl and it had been added only since FreeBSD14. + # And since sysroot has older libraries you will got undefined reference for clickhouse binary. + # + # But likely everything should work without this syscall, however it is not + # possible right now to gently override libraries versions for dependencies, + # and forking rust modules is a little bit too much for this thing. + # + # You can take a look at the details in the following issue [1]. + # + # [1]: https://github.com/rust-lang/cargo/issues/5640 + # + # Update 2024-04: Now prql also requires getrandom() via std::sys::pal::unix::rand::imp::getrandom_fill_bytes + message(STATUS "Rust build is disabled for FreeBSD because we use old sysroot files") + return() +endif() + +clickhouse_import_crate(MANIFEST_PATH Cargo.toml) +clickhouse_config_crate_flags(_ch_rust_prql) +clickhouse_config_crate_flags(_ch_rust_skim_rust) + +target_include_directories(_ch_rust_prql INTERFACE prql/include) +add_library(ch_rust::prql ALIAS _ch_rust_prql) + +target_include_directories(_ch_rust_skim_rust INTERFACE skim/include) +add_library(ch_rust::skim ALIAS _ch_rust_skim_rust) \ No newline at end of file diff --git a/rust/workspace/Cargo.lock b/rust/workspace/Cargo.lock new file mode 100644 index 00000000000..850922fefc8 --- /dev/null +++ b/rust/workspace/Cargo.lock @@ -0,0 +1,1733 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "_ch_rust_prql" +version = "0.1.0" +dependencies = [ + "anstream", + "prqlc", + "serde_json", +] + +[[package]] +name = "_ch_rust_skim_rust" +version = "0.1.0" +dependencies = [ + "clap", + "cxx", + "cxx-build", + "skim", + "term 1.0.0", +] + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anstream" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + +[[package]] +name = "anstyle-parse" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +dependencies = [ + "anstyle", + "windows-sys 0.59.0", +] + +[[package]] +name = "anyhow" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" + +[[package]] +name = "ariadne" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44055e597c674aef7cb903b2b9f6e4cba1277ed0d2d61dae7cd52d7ffa81f8e2" +dependencies = [ + "unicode-width 0.1.14", + "yansi", +] + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "beef" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bstr" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a68f1f47cdf0ec8ee4b941b2eee2a80cb796db73118c0dd09ac63fbe405be22" +dependencies = [ + "memchr", + "regex-automata", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cc" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-targets", +] + +[[package]] +name = "chumsky" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eebd66744a15ded14960ab4ccdbfb51ad3b81f51f3f04a80adac98c985396c9" +dependencies = [ + "hashbrown 0.14.5", + "stacker", +] + +[[package]] +name = "clap" +version = "4.5.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69371e34337c4c984bbe322360c2547210bf632eb2814bbe78a6e87a2935bd2b" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e24c1b4099818523236a8ca881d2b45db98dadfb4625cf6608c12069fcbbde1" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width 0.1.14", +] + +[[package]] +name = "colorchoice" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "crossbeam" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "csv" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" +dependencies = [ + "memchr", +] + +[[package]] +name = "cxx" +version = "1.0.133" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05e1ec88093d2abd9cf1b09ffd979136b8e922bf31cad966a8fe0d73233112ef" +dependencies = [ + "cc", + "cxxbridge-cmd", + "cxxbridge-flags", + "cxxbridge-macro", + "foldhash", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.133" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afa390d956ee7ccb41aeed7ed7856ab3ffb4fc587e7216be7e0f83e949b4e6c" +dependencies = [ + "cc", + "codespan-reporting", + "proc-macro2", + "quote", + "scratch", + "syn", +] + +[[package]] +name = "cxxbridge-cmd" +version = "1.0.133" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c23bfff654d6227cbc83de8e059d2f8678ede5fc3a6c5a35d5c379983cc61e6" +dependencies = [ + "clap", + "codespan-reporting", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.133" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c01b36e22051bc6928a78583f1621abaaf7621561c2ada1b00f7878fbe2caa" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.133" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6e14013136fac689345d17b9a6df55977251f11d333c0a571e8d963b55e1f95" +dependencies = [ + "proc-macro2", + "quote", + "rustversion", + "syn", +] + +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "defer-drop" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f613ec9fa66a6b28cdb1842b27f9adf24f39f9afc4dcdd9fdecee4aca7945c57" +dependencies = [ + "crossbeam-channel", + "once_cell", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "derive_builder" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" +dependencies = [ + "derive_builder_core", + "syn", +] + +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "enum-as-inner" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "env_filter" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "humantime", + "log", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" + +[[package]] +name = "fuzzy-matcher" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54614a3312934d066701a80f20f15fa3b56d67ac7722b39eea5b4c9dd1d66c94" +dependencies = [ + "thread_local", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "iana-time-zone" +version = "0.1.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "indexmap" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +dependencies = [ + "equivalent", + "hashbrown 0.15.2", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" + +[[package]] +name = "js-sys" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a865e038f7f6ed956f788f0d7d60c541fff74c7bd74272c5d4cf15c63743e705" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.167" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" + +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.6.0", + "libc", +] + +[[package]] +name = "link-cplusplus" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d240c6f7e1ba3a28b0249f774e6a9dd0175054b52dfbb61b16eb8505c3785c9" +dependencies = [ + "cc", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nix" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", +] + +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.6.0", + "cfg-if", + "cfg_aliases", + "libc", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_threads" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prqlc" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4e46dd8e5e577feadd15c1f30c1e703cb9b34ee06ebf167526fc54aa22cfefb" +dependencies = [ + "anstream", + "ariadne", + "chrono", + "csv", + "enum-as-inner", + "itertools", + "log", + "prqlc-parser", + "regex", + "schemars", + "semver", + "serde", + "serde_json", + "sqlformat", + "sqlparser", + "strum", + "strum_macros", + "vergen-gitcl", +] + +[[package]] +name = "prqlc-parser" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ea2bceb578101432556cf8798f252657ef48f7f502d450dac083d663c40c6db" +dependencies = [ + "chumsky", + "enum-as-inner", + "itertools", + "log", + "schemars", + "semver", + "serde", + "stacker", + "strum", +] + +[[package]] +name = "psm" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "200b9ff220857e53e184257720a14553b2f4aa02577d2ed9842d45d4b9654810" +dependencies = [ + "cc", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + +[[package]] +name = "ref-cast" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rustix" +version = "0.38.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" +dependencies = [ + "bitflags 2.6.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustversion" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "schemars" +version = "1.0.0-alpha.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ef2a6523400a2228db974a8ddc9e1d3deaa04f51bddd7832ef8d7e531bafcc" +dependencies = [ + "dyn-clone", + "ref-cast", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "1.0.0-alpha.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6d4e1945a3c9e58edaa708449b026519f7f4197185e1b5dbc689615c1ad724d" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn", +] + +[[package]] +name = "scratch" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3cf7c11c38cb994f3d40e8a8cde3bbd1f72a435e4c49e85d6553d8312306152" + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +dependencies = [ + "serde", +] + +[[package]] +name = "serde" +version = "1.0.215" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.215" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_derive_internals" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.133" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "shell-quote" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae4c63bdcc11eea49b562941b914d5ac30d42cad982e3f6e846a513ee6a3ce7e" +dependencies = [ + "bstr", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "skim" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "713b5a46e3df69e892e024779d2c5418e886d52454b150569962a04c0ed88c61" +dependencies = [ + "atty", + "beef", + "bitflags 1.3.2", + "chrono", + "clap", + "crossbeam", + "defer-drop", + "derive_builder", + "env_logger", + "fuzzy-matcher", + "indexmap", + "lazy_static", + "log", + "nix 0.29.0", + "rand", + "rayon", + "regex", + "shell-quote", + "shlex", + "time", + "timer", + "tuikit", + "unicode-width 0.2.0", + "vte", + "which", +] + +[[package]] +name = "sqlformat" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bba3a93db0cc4f7bdece8bb09e77e2e785c20bfebf79eb8340ed80708048790" +dependencies = [ + "nom", + "unicode_categories", +] + +[[package]] +name = "sqlparser" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fe11944a61da0da3f592e19a45ebe5ab92dc14a779907ff1f08fbb797bfefc7" +dependencies = [ + "log", + "serde", +] + +[[package]] +name = "stacker" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799c883d55abdb5e98af1a7b3f23b9b6de8ecada0ecac058672d7635eb48ca7b" +dependencies = [ + "cc", + "cfg-if", + "libc", + "psm", + "windows-sys 0.59.0", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn", +] + +[[package]] +name = "syn" +version = "2.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi", +] + +[[package]] +name = "term" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4df4175de05129f31b80458c6df371a15e7fc3fd367272e6bf938e5c351c7ea0" +dependencies = [ + "home", + "windows-sys 0.52.0", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "time" +version = "0.3.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" +dependencies = [ + "deranged", + "itoa", + "libc", + "num-conv", + "num_threads", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "timer" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31d42176308937165701f50638db1c31586f183f1aab416268216577aec7306b" +dependencies = [ + "chrono", +] + +[[package]] +name = "tuikit" +version = "0.5.0" +source = "git+https://github.com/azat-rust/tuikit.git?rev=e1994c0e03ff02c49cf1471f0cc3cbf185ce0104#e1994c0e03ff02c49cf1471f0cc3cbf185ce0104" +dependencies = [ + "bitflags 1.3.2", + "lazy_static", + "log", + "nix 0.24.3", + "term 0.7.0", + "unicode-width 0.1.14", +] + +[[package]] +name = "unicode-ident" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unicode-width" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" + +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "vergen" +version = "9.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f25fc8f8f05df455c7941e87f093ad22522a9ff33d7a027774815acf6f0639" +dependencies = [ + "anyhow", + "derive_builder", + "rustversion", + "time", + "vergen-lib", +] + +[[package]] +name = "vergen-gitcl" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0227006d09f98ab00ea69e9a5e055e676a813cfbed4232986176c86a6080b997" +dependencies = [ + "anyhow", + "derive_builder", + "rustversion", + "time", + "vergen", + "vergen-lib", +] + +[[package]] +name = "vergen-lib" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0c767e6751c09fc85cde58722cf2f1007e80e4c8d5a4321fc90d83dc54ca147" +dependencies = [ + "anyhow", + "derive_builder", + "rustversion", +] + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "vte" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40eb22ae96f050e0c0d6f7ce43feeae26c348fc4dea56928ca81537cfaa6188b" +dependencies = [ + "arrayvec", + "utf8parse", + "vte_generate_state_changes", +] + +[[package]] +name = "vte_generate_state_changes" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e369bee1b05d510a7b4ed645f5faa90619e05437111783ea5848f28d97d3c2e" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d15e63b4482863c109d70a7b8706c1e364eb6ea449b201a76c5b89cedcec2d5c" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d36ef12e3aaca16ddd3f67922bc63e48e953f126de60bd33ccc0101ef9998cd" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "705440e08b42d3e4b36de7d66c944be628d579796b8090bfa3471478a2260051" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98c9ae5a76e46f4deecd0f0255cc223cfa18dc9b261213b8aa0c7b36f61b3f1d" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ee99da9c5ba11bd675621338ef6fa52296b76b83305e9b6e5c77d4c286d6d49" + +[[package]] +name = "which" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9cad3279ade7346b96e38731a641d7343dd6a53d55083dd54eadfa5a1b38c6b" +dependencies = [ + "either", + "home", + "rustix", + "winsafe", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winsafe" +version = "0.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" + +[[package]] +name = "yansi" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/rust/workspace/Cargo.toml b/rust/workspace/Cargo.toml new file mode 100644 index 00000000000..a830fc09f1c --- /dev/null +++ b/rust/workspace/Cargo.toml @@ -0,0 +1,11 @@ +# workspace is required to vendor crates for all packages. +[workspace] +members = [ + "skim", + "prql", +] +resolver = "2" + +[patch.crates-io] +# Ref: https://github.com/lotabout/tuikit/pull/51 +tuikit = { git = "https://github.com/azat-rust/tuikit.git", rev = "e1994c0e03ff02c49cf1471f0cc3cbf185ce0104" } diff --git a/rust/workspace/prql/Cargo.toml b/rust/workspace/prql/Cargo.toml new file mode 100644 index 00000000000..26e70fd399e --- /dev/null +++ b/rust/workspace/prql/Cargo.toml @@ -0,0 +1,12 @@ +[package] +edition = "2021" +name = "_ch_rust_prql" +version = "0.1.0" + +[dependencies] +anstream = {version = "0.6.12"} +prqlc = {version = "0.13.2", default-features = false} +serde_json = "1.0" + +[lib] +crate-type = ["staticlib"] diff --git a/rust/workspace/prql/include/prql.h b/rust/workspace/prql/include/prql.h new file mode 100644 index 00000000000..29158d7f30d --- /dev/null +++ b/rust/workspace/prql/include/prql.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +extern "C" { + +/// Converts a PRQL query to an SQL query. +/// @param query is a pointer to the beginning of the PRQL query. +/// @param size is the size of the PRQL query. +/// @param out is a pointer to a uint8_t pointer which will be set to the beginning of the null terminated SQL query or the error message. +/// @param out_size is the size of the string pointed by `out`. +/// @returns zero in case of success, non-zero in case of failure. +int64_t prql_to_sql(const uint8_t * query, uint64_t size, uint8_t ** out, uint64_t * out_size); + +/// Frees the passed in pointer which's memory was allocated by Rust allocators previously. +void prql_free_pointer(uint8_t * ptr_to_free); + +} // extern "C" diff --git a/rust/workspace/prql/src/lib.rs b/rust/workspace/prql/src/lib.rs new file mode 100644 index 00000000000..920e2e96b69 --- /dev/null +++ b/rust/workspace/prql/src/lib.rs @@ -0,0 +1,109 @@ +use prqlc::sql::Dialect; +use prqlc::{Options, Target}; +use std::ffi::{c_char, CString}; +use std::panic; +use std::slice; + +fn set_output(result: String, out: *mut *mut u8, out_size: *mut u64) { + assert!(!out_size.is_null()); + let out_size_ptr = unsafe { &mut *out_size }; + *out_size_ptr = (result.len() + 1).try_into().unwrap(); + + assert!(!out.is_null()); + let out_ptr = unsafe { &mut *out }; + *out_ptr = CString::new(result).unwrap().into_raw() as *mut u8; +} + +/// Converts a PRQL query from a raw C string to SQL, returning an error code if the conversion fails. +pub unsafe extern "C" fn prql_to_sql_impl( + query: *const u8, + size: u64, + out: *mut *mut u8, + out_size: *mut u64, +) -> i64 { + let query_vec = slice::from_raw_parts(query, size.try_into().unwrap()).to_vec(); + let Ok(query_str) = String::from_utf8(query_vec) else { + set_output( + "The PRQL query must be UTF-8 encoded!".to_string(), + out, + out_size, + ); + return 1; + }; + + let opts = Options { + format: true, + target: Target::Sql(Some(Dialect::ClickHouse)), + signature_comment: false, + color: false, + display: prqlc::DisplayOptions::Plain, + }; + + if let Ok(sql_str) = prqlc::compile(&query_str, &opts) { + // NOTE: Over at PRQL we're considering to un-deprecate & re-enable the + // `color: false` option. If that happens, we can remove the `strip_str` + // here, which strips color codes from the output. + use anstream::adapter::strip_str; + let sql_str = strip_str(&sql_str).to_string(); + set_output(sql_str, out, out_size); + 0 + } else { + set_output("PRQL compilation failed!".to_string(), out, out_size); + 1 + } +} + +#[no_mangle] +pub unsafe extern "C" fn prql_to_sql( + query: *const u8, + size: u64, + out: *mut *mut u8, + out_size: *mut u64, +) -> i64 { + // NOTE: using cxxbridge we can return proper Result<> type. + panic::catch_unwind(|| prql_to_sql_impl(query, size, out, out_size)).unwrap_or_else(|_| { + set_output("prqlc panicked".to_string(), out, out_size); + 1 + }) +} + +#[no_mangle] +pub unsafe extern "C" fn prql_free_pointer(ptr_to_free: *mut u8) { + std::mem::drop(CString::from_raw(ptr_to_free as *mut c_char)); +} + +#[cfg(test)] +mod tests { + use super::*; + use std::ffi::{CStr, CString}; + + /// A test helper to offer a rust interface to the C bindings + fn run_compile(query: &str) -> (String, i64) { + let query_cstr = CString::new(query).unwrap(); + let query_ptr = query_cstr.as_ptr() as *const u8; + let query_size = query_cstr.to_bytes_with_nul().len() as u64 - 1; // Excluding the null terminator + + let mut out: *mut u8 = std::ptr::null_mut(); + let mut out_size = 0_u64; + + unsafe { + let success = prql_to_sql(query_ptr, query_size, &mut out, &mut out_size); + let output = CStr::from_ptr(out as *const i8) + .to_str() + .unwrap() + .to_string(); + prql_free_pointer(out); + (output, success) + } + } + + #[test] + fn test_prql_to_sql() { + assert!(run_compile("from x").0.contains("SELECT")); + assert!(run_compile("asdf").1 == 1); + // In prqlc 0.11.3, this is a panic, so that allows us to test that the + // panic is caught. When we upgrade prqlc, it won't be a panic any + // longer. + assert!(run_compile("x -> y").1 == 1); + } +} diff --git a/rust/workspace/skim/.gitignore b/rust/workspace/skim/.gitignore new file mode 100644 index 00000000000..9ebbc84ba4a --- /dev/null +++ b/rust/workspace/skim/.gitignore @@ -0,0 +1,2 @@ +build.rs +.cargo/config.toml diff --git a/rust/workspace/skim/Cargo.toml b/rust/workspace/skim/Cargo.toml new file mode 100644 index 00000000000..e153e9058ae --- /dev/null +++ b/rust/workspace/skim/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "_ch_rust_skim_rust" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +skim = { version = "0.15.5", default-features = false, features = ["cli"] } +cxx = "1.0.83" +term = "1.0.0" +clap = "4.5.22" + +[build-dependencies] +cxx-build = "1.0.83" + +[lib] +crate-type = ["staticlib"] diff --git a/rust/workspace/skim/build.rs b/rust/workspace/skim/build.rs new file mode 100644 index 00000000000..7856e8239c0 --- /dev/null +++ b/rust/workspace/skim/build.rs @@ -0,0 +1,4 @@ +fn main() { + let build = cxx_build::bridge("src/lib.rs"); + build.compile("skim"); +} diff --git a/rust/workspace/skim/include/skim.h b/rust/workspace/skim/include/skim.h new file mode 100644 index 00000000000..8148474eba3 --- /dev/null +++ b/rust/workspace/skim/include/skim.h @@ -0,0 +1,90 @@ +/// This header was compiled with: +/// +/// $ cxxbridge rust/skim/src/lib.rs --header +/// +/// For more info [1]. +/// +/// [1]: https://cxx.rs/build/other.html + +#pragma once +#include +#include +#include +#include + +namespace rust { +inline namespace cxxbridge1 { +// #include "rust/cxx.h" + +struct unsafe_bitcopy_t; + +#ifndef CXXBRIDGE1_RUST_STRING +#define CXXBRIDGE1_RUST_STRING +class String final { +public: + String() noexcept; + String(const String &) noexcept; + String(String &&) noexcept; + ~String() noexcept; + + String(const std::string &); + String(const char *); + String(const char *, std::size_t); + String(const char16_t *); + String(const char16_t *, std::size_t); + + static String lossy(const std::string &) noexcept; + static String lossy(const char *) noexcept; + static String lossy(const char *, std::size_t) noexcept; + static String lossy(const char16_t *) noexcept; + static String lossy(const char16_t *, std::size_t) noexcept; + + String &operator=(const String &) &noexcept; + String &operator=(String &&) &noexcept; + + explicit operator std::string() const; + + const char *data() const noexcept; + std::size_t size() const noexcept; + std::size_t length() const noexcept; + bool empty() const noexcept; + + const char *c_str() noexcept; + + std::size_t capacity() const noexcept; + void reserve(size_t new_cap) noexcept; + + using iterator = char *; + iterator begin() noexcept; + iterator end() noexcept; + + using const_iterator = const char *; + const_iterator begin() const noexcept; + const_iterator end() const noexcept; + const_iterator cbegin() const noexcept; + const_iterator cend() const noexcept; + + bool operator==(const String &) const noexcept; + bool operator!=(const String &) const noexcept; + bool operator<(const String &) const noexcept; + bool operator<=(const String &) const noexcept; + bool operator>(const String &) const noexcept; + bool operator>=(const String &) const noexcept; + + void swap(String &) noexcept; + + String(unsafe_bitcopy_t, const String &) noexcept; + +private: + struct lossy_t; + String(lossy_t, const char *, std::size_t) noexcept; + String(lossy_t, const char16_t *, std::size_t) noexcept; + friend void swap(String &lhs, String &rhs) noexcept { lhs.swap(rhs); } + + std::array repr; +}; +#endif // CXXBRIDGE1_RUST_STRING +} // namespace cxxbridge1 +} // namespace rust + +::rust::String skim(::std::string const &prefix, ::std::vector<::std::string> const &words); diff --git a/rust/workspace/skim/src/lib.rs b/rust/workspace/skim/src/lib.rs new file mode 100644 index 00000000000..cb18564053d --- /dev/null +++ b/rust/workspace/skim/src/lib.rs @@ -0,0 +1,113 @@ +use cxx::{CxxString, CxxVector}; +use skim::prelude::*; +use std::panic; +use term::terminfo::TermInfo; + +#[cxx::bridge] +mod ffi { + extern "Rust" { + fn skim(prefix: &CxxString, words: &CxxVector) -> Result; + } +} + +struct Item { + text_no_newlines: String, + orig_text: String, +} +impl Item { + fn new(text: String) -> Self { + Self { + // Text that will be printed by skim, and will be used for matching. + // + // Text that will be shown should not contains new lines since in this case skim may + // live some symbols on the screen, and this looks odd. + text_no_newlines: text.replace("\n", " "), + // This will be used when the match had been selected. + orig_text: text, + } + } +} +impl SkimItem for Item { + fn text(&self) -> Cow { + Cow::Borrowed(&self.text_no_newlines) + } + + fn output(&self) -> Cow { + Cow::Borrowed(&self.orig_text) + } +} + +fn skim_impl(prefix: &CxxString, words: &CxxVector) -> Result { + // Let's check is terminal available. To avoid panic. + if let Err(err) = TermInfo::from_env() { + return Err(format!("{}", err)); + } + + let options = SkimOptionsBuilder::default() + .height("30%".to_string()) + .query(Some(prefix.to_str().unwrap().to_string())) + .tac(true) + // Do not clear on start and clear on exit will clear skim output from the terminal. + // + // Refs: https://github.com/lotabout/skim/issues/494#issuecomment-1776565846 + .no_clear_start(true) + .no_clear(false) + .tiebreak(vec![RankCriteria::NegScore]) + // Exact mode performs better for SQL. + // + // Default fuzzy search is too smart for SQL, it even takes into account the case, which + // should not be accounted (you don't want to type "SELECT" instead of "select" to find the + // query). + // + // Exact matching seems better algorithm for SQL, it is not 100% exact, it splits by space, + // and apply separate matcher actually for each word. + // Note, that if you think that "space is not enough" as the delimiter, then you should + // first know that this is the delimiter only for the input query, so to match + // "system.query_log" you can use "sy qu log" + // Also it should be more common for users who did not know how to use fuzzy search. + // (also you can disable exact mode by prepending "'" char). + // + // Also it ignores the case correctly, i.e. it does not have penalty for case mismatch, + // like fuzzy algorithms (take a look at SkimScoreConfig::penalty_case_mismatch). + .exact(true) + .case(CaseMatching::Ignore) + .build() + .unwrap(); + + let (tx, rx): (SkimItemSender, SkimItemReceiver) = unbounded(); + for word in words { + tx.send(Arc::new(Item::new(word.to_string()))).unwrap(); + } + // so that skim could know when to stop waiting for more items. + drop(tx); + + let output = Skim::run_with(&options, Some(rx)); + if output.is_none() { + return Err("skim return nothing".to_string()); + } + let output = output.unwrap(); + if output.is_abort { + return Ok("".to_string()); + } + + if output.selected_items.is_empty() { + return Err("No items had been selected".to_string()); + } + Ok(output.selected_items[0].output().to_string()) +} + +fn skim(prefix: &CxxString, words: &CxxVector) -> Result { + match panic::catch_unwind(|| skim_impl(prefix, words)) { + Err(err) => { + let e = if let Some(s) = err.downcast_ref::() { + format!("{}", s) + } else if let Some(s) = err.downcast_ref::<&str>() { + format!("{}", s) + } else { + format!("Unknown panic type: {:?}", err.type_id()) + }; + Err(format!("Rust panic: {:?}", e)) + } + Ok(res) => res, + } +} diff --git a/tests/test_delta_lake.py b/tests/test_delta_lake.py new file mode 100644 index 00000000000..c89d2787341 --- /dev/null +++ b/tests/test_delta_lake.py @@ -0,0 +1,32 @@ +#!python3 + +import unittest +import sys +import platform +import chdb +from chdb import session + +@unittest.skipUnless(sys.platform.startswith("linux") and platform.machine() in ["x86_64", "AMD64"], "Runs only in the Linux x86 environment") +class TestDeltaLake(unittest.TestCase): + def setUp(self) -> None: + return super().setUp() + + def tearDown(self) -> None: + return super().tearDown() + + def test_delta_lake(self): + sess = session.Session() + + ret = sess.query( + ''' + SELECT + URL, + UserAgent + FROM deltaLake('https://clickhouse-public-datasets.s3.amazonaws.com/delta_lake/hits/') + WHERE URL IS NULL + LIMIT 2 + ''') + self.assertEqual(ret.rows_read(), 0) + +if __name__ == "__main__": + unittest.main()