pax_global_header00006660000000000000000000000064145323667410014525gustar00rootroot0000000000000052 comment=03afe5c6c64e1f872b2933ee863ee0085e837a00 oxigraph-0.3.22/000077500000000000000000000000001453236674100134325ustar00rootroot00000000000000oxigraph-0.3.22/.cargo/000077500000000000000000000000001453236674100146035ustar00rootroot00000000000000oxigraph-0.3.22/.cargo/config.toml000066400000000000000000000120561453236674100167510ustar00rootroot00000000000000[build] rustflags = [ "-Wtrivial-casts", "-Wtrivial-numeric-casts", "-Wunsafe-code", "-Wunused-lifetimes", "-Wunused-qualifications", # TODO: 1.63+ "-Wclippy::as-underscore", # TODO: 1.65+ ""-Wclippy::bool-to-int-with-if", "-Wclippy::borrow-as-ptr", "-Wclippy::case-sensitive-file-extension-comparisons", "-Wclippy::cast-lossless", "-Wclippy::cast-possible-truncation", "-Wclippy::cast-possible-wrap", "-Wclippy::cast-precision-loss", "-Wclippy::cast-ptr-alignment", "-Wclippy::cast-sign-loss", "-Wclippy::checked-conversions", "-Wclippy::clone-on-ref-ptr", "-Wclippy::cloned-instead-of-copied", "-Wclippy::copy-iterator", "-Wclippy::dbg-macro", "-Wclippy::decimal-literal-representation", "-Wclippy::default-trait-access", "-Wclippy::default-union-representation", # TODO: 1.61+ "-Wclippy::deref-by-slicing", # TODO: 1.63+ "-Wclippy::doc-link-with-quotes", # TODO: 1.62+ "-Wclippy::empty-drop", "-Wclippy::empty-enum", # TODO: on major version "-Wclippy::empty-structs-with-brackets", "-Wclippy::enum-glob-use", "-Wclippy::exit", "-Wclippy::expect-used", "-Wclippy::expl-impl-clone-on-copy", "-Wclippy::explicit-deref-methods", "-Wclippy::explicit-into-iter-loop", "-Wclippy::explicit-iter-loop", "-Wclippy::filter-map-next", "-Wclippy::flat-map-option", "-Wclippy::fn-to-numeric-cast-any", # TODO: 1.62+ "-Wclippy::format-push-string", "-Wclippy::from-iter-instead-of-collect", "-Wclippy::get-unwrap", "-Wclippy::if-not-else", "-Wclippy::if-then-some-else-none", "-Wclippy::implicit-clone", "-Wclippy::inconsistent-struct-constructor", "-Wclippy::index-refutable-slice", "-Wclippy::inefficient-to-string", "-Wclippy::inline-always", "-Wclippy::inline-asm-x86-att-syntax", "-Wclippy::inline-asm-x86-intel-syntax", "-Wclippy::invalid-upcast-comparisons", "-Wclippy::items-after-statements", "-Wclippy::large-digit-groups", # TODO: 1.68+ "-Wclippy::large-futures", "-Wclippy::large-stack-arrays", "-Wclippy::large-types-passed-by-value", "-Wclippy::let-underscore-must-use", "-Wclippy::let-unit-value", "-Wclippy::linkedlist", "-Wclippy::lossy-float-literal", "-Wclippy::macro-use-imports", "-Wclippy::manual-assert", # TODO: 1.65+ "-Wclippy::manual-instant-elapsed", # TODO: 1.67+ "-Wclippy::manual-let-else", "-Wclippy::manual-ok-or", # TODO: 1.65+ "-Wclippy::manual-string-new", "-Wclippy::many-single-char-names", "-Wclippy::map-unwrap-or", "-Wclippy::match-bool", "-Wclippy::match-same-arms", "-Wclippy::match-wildcard-for-single-variants", "-Wclippy::maybe-infinite-iter", "-Wclippy::mem-forget", # TODO: 1.63+ "-Wclippy::mismatching-type-param-order", "-Wclippy::multiple-inherent-impl", "-Wclippy::mut-mut", "-Wclippy::mutex-atomic", "-Wclippy::naive-bytecount", "-Wclippy::needless-bitwise-bool", "-Wclippy::needless-continue", "-Wclippy::needless-pass-by-value", "-Wclippy::no-effect-underscore-binding", # TODO: 1.69+ "-Wclippy::no-mangle-with-rust-abi", "-Wclippy::non-ascii-literal", "-Wclippy::print-stderr", "-Wclippy::print-stdout", "-Wclippy::ptr-as-ptr", "-Wclippy::range-minus-one", "-Wclippy::range-plus-one", "-Wclippy::rc-buffer", "-Wclippy::rc-mutex", "-Wclippy::redundant-closure-for-method-calls", "-Wclippy::redundant-else", "-Wclippy::redundant-feature-names", "-Wclippy::ref-binding-to-reference", "-Wclippy::ref-option-ref", "-Wclippy::rest-pat-in-fully-bound-structs", "-Wclippy::return-self-not-must-use", "-Wclippy::same-functions-in-if-condition", # TODO: strange failure on 1.60 "-Wclippy::same-name-method", # TODO: 1.68+ "-Wclippy::semicolon-outside-block", "-Wclippy::single-match-else", "-Wclippy::stable-sort-primitive", "-Wclippy::str-to-string", "-Wclippy::string-add", "-Wclippy::string-add-assign", "-Wclippy::string-lit-as-bytes", "-Wclippy::string-to-string", # TODO: 1.67+ "-Wclippy::suspicious-xor-used-as-pow", "-Wclippy::todo", "-Wclippy::transmute-ptr-to-ptr", "-Wclippy::trivially-copy-pass-by-ref", "-Wclippy::try-err", "-Wclippy::unicode-not-nfc", "-Wclippy::unimplemented", # TODO: 1.66+ "-Wclippy::uninlined-format-args", # TODO: 1.70+ "-Wclippy::unnecessary-box-returns", # TODO: 1.61+ "-Wclippy::unnecessary-join", # TODO: 1.67+ "-Wclippy::unnecessary-safety-comment", # TODO: 1.67+ "-Wclippy::unnecessary-safety-doc", "-Wclippy::unnecessary-self-imports", "-Wclippy::unnecessary-wraps", "-Wclippy::unneeded-field-pattern", "-Wclippy::unnested-or-patterns", "-Wclippy::unreadable-literal", "-Wclippy::unseparated-literal-suffix", "-Wclippy::unused-async", "-Wclippy::unused-self", "-Wclippy::use-debug", "-Wclippy::used-underscore-binding", "-Wclippy::verbose-bit-mask", "-Wclippy::verbose-file-reads", "-Wclippy::wildcard-dependencies", "-Wclippy::zero-sized-map-values", ]oxigraph-0.3.22/.clusterfuzzlite/000077500000000000000000000000001453236674100167665ustar00rootroot00000000000000oxigraph-0.3.22/.clusterfuzzlite/Dockerfile000066400000000000000000000003771453236674100207670ustar00rootroot00000000000000FROM gcr.io/oss-fuzz-base/base-builder-rust:v1 RUN apt-get update && apt-get install -y llvm-dev libclang-dev clang && apt-get clean && rm --recursive --force /var/lib/apt/lists/* COPY . $SRC/oxigraph WORKDIR oxigraph COPY .clusterfuzzlite/build.sh $SRC/ oxigraph-0.3.22/.clusterfuzzlite/build.sh000077500000000000000000000012561453236674100204300ustar00rootroot00000000000000#!/bin/bash -eu shopt -s globstar function build_seed_corpus() { mkdir "/tmp/oxigraph_$1" for file in **/*."$2" do hash=$(sha256sum "$file" | awk '{print $1;}') cp "$file" "/tmp/oxigraph_$1/$hash" done zip "$1_seed_corpus.zip" /tmp/"oxigraph_$1"/* rm -r "/tmp/oxigraph_$1" } cd "$SRC"/oxigraph cargo fuzz build -O --debug-assertions for TARGET in sparql_eval sparql_results_json sparql_results_tsv # sparql_results_xml https://github.com/tafia/quick-xml/issues/608 do cp fuzz/target/x86_64-unknown-linux-gnu/release/$TARGET "$OUT"/ done build_seed_corpus sparql_results_json srj build_seed_corpus sparql_results_tsv tsv build_seed_corpus sparql_results_xml srx oxigraph-0.3.22/.clusterfuzzlite/project.yaml000066400000000000000000000000171453236674100213160ustar00rootroot00000000000000language: rust oxigraph-0.3.22/.devcontainer/000077500000000000000000000000001453236674100161715ustar00rootroot00000000000000oxigraph-0.3.22/.devcontainer/Dockerfile000066400000000000000000000014701453236674100201650ustar00rootroot00000000000000# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.241.1/containers/rust/.devcontainer/base.Dockerfile # [Choice] Debian OS version (use bullseye on local arm64/Apple Silicon): buster, bullseye ARG VARIANT="bullseye" FROM mcr.microsoft.com/vscode/devcontainers/rust:0-${VARIANT} # [Optional] Uncomment this section to install additional packages. RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ && apt-get -y install --no-install-recommends \ python3 \ python3-venv \ python-is-python3 \ libclang-dev ENV VIRTUAL_ENV=/opt/venv RUN python -m venv $VIRTUAL_ENV ENV PATH="$VIRTUAL_ENV/bin:$PATH" RUN pip install --no-cache-dir -r python/requirements.dev.txt # Change owner to the devcontainer user RUN chown -R 1000:1000 $VIRTUAL_ENV oxigraph-0.3.22/.devcontainer/devcontainer.json000066400000000000000000000052431453236674100215510ustar00rootroot00000000000000// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: // https://github.com/microsoft/vscode-dev-containers/tree/v0.241.1/containers/rust { "name": "Rust", "build": { "dockerfile": "Dockerfile", "args": { // Use the VARIANT arg to pick a Debian OS version: buster, bullseye // Use bullseye when on local on arm64/Apple Silicon. "VARIANT": "bullseye" } }, "runArgs": ["--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined"], // Configure tool-specific properties. "customizations": { // Configure properties specific to VS Code. "vscode": { // Set *default* container specific settings.json values on container create. "settings": { "lldb.executable": "/usr/bin/lldb", // VS Code don't watch files under ./target "files.watcherExclude": { "**/target/**": true }, "rust-analyzer.checkOnSave.command": "clippy", "python.defaultInterpreterPath": "/opt/venv/bin/python", "python.linting.enabled": true, "python.linting.pylintEnabled": true, "python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8", "python.formatting.blackPath": "/usr/local/py-utils/bin/black", "python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf", "python.linting.banditPath": "/usr/local/py-utils/bin/bandit", "python.linting.flake8Path": "/usr/local/py-utils/bin/flake8", "python.linting.mypyPath": "/usr/local/py-utils/bin/mypy", "python.linting.pycodestylePath": "/usr/local/py-utils/bin/pycodestyle", "python.linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle", "python.linting.pylintPath": "/opt/venv/bin/pylint", "python.testing.pytestPath": "/opt/venv/bin/pytest" }, // Add the IDs of extensions you want installed when the container is created. "extensions": [ "vadimcn.vscode-lldb", "mutantdino.resourcemonitor", "rust-lang.rust-analyzer", "tamasfe.even-better-toml", "serayuzgur.crates", "ms-python.python", "ms-python.vscode-pylance", "esbenp.prettier-vscode", "stardog-union.stardog-rdf-grammars" ] } }, // Use 'forwardPorts' to make a list of ports inside the container available locally. // "forwardPorts": [], // Use 'postCreateCommand' to run commands after the container is created. "postCreateCommand": "git submodule update --init && cargo build", // Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. "remoteUser": "vscode", "features": { "python": "3.10" } } oxigraph-0.3.22/.dockerignore000066400000000000000000000000051453236674100161010ustar00rootroot00000000000000benchoxigraph-0.3.22/.github/000077500000000000000000000000001453236674100147725ustar00rootroot00000000000000oxigraph-0.3.22/.github/DEPENDABOT.yml000066400000000000000000000006061453236674100171240ustar00rootroot00000000000000version: 2 updates: - package-ecosystem: "github-actions" directory: "/" schedule: interval: weekly - package-ecosystem: "pip" directory: "/python/" versioning-strategy: increase-if-necessary schedule: interval: weekly - package-ecosystem: "npm" directory: "/js/" versioning-strategy: increase-if-necessary schedule: interval: weekly oxigraph-0.3.22/.github/FUNDING.yml000066400000000000000000000000201453236674100165770ustar00rootroot00000000000000github: [ Tpt ] oxigraph-0.3.22/.github/ISSUE_TEMPLATE/000077500000000000000000000000001453236674100171555ustar00rootroot00000000000000oxigraph-0.3.22/.github/ISSUE_TEMPLATE/bug_report.md000066400000000000000000000005371453236674100216540ustar00rootroot00000000000000--- name: Bug report about: Create a report to help us improve title: '' labels: bug assignees: '' --- **Describe the bug** A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behavior: 1. Which version of Oxigraph are you using? On which platform? 2. A command line or a code snippet that triggers the bug. oxigraph-0.3.22/.github/ISSUE_TEMPLATE/feature-request.md000066400000000000000000000012411453236674100226160ustar00rootroot00000000000000--- name: Feature request about: Suggest an idea for this project title: '' labels: enhancement assignees: '' --- **Is your feature request related to a problem? Please describe.** A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] **Describe the solution you'd like** A clear and concise description of what you want to happen. **Describe alternatives you've considered** A clear and concise description of any alternative solutions or features you've considered. **Additional context** Please link to other systems implementing the feature, specification of it if it exists and/or existing documentation about this feature. oxigraph-0.3.22/.github/ISSUE_TEMPLATE/question.md000066400000000000000000000002211453236674100213410ustar00rootroot00000000000000--- name: Question about: Please don't use issues but the Q&A section of the "discussions" space title: '' labels: question assignees: '' --- oxigraph-0.3.22/.github/workflows/000077500000000000000000000000001453236674100170275ustar00rootroot00000000000000oxigraph-0.3.22/.github/workflows/artifacts.yml000066400000000000000000000363251453236674100215430ustar00rootroot00000000000000name: Artifacts on: push: branches: - main release: types: - published concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: binary_linux: runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v3 with: submodules: true - run: rustup update && rustup target add aarch64-unknown-linux-gnu - run: | sudo apt update && sudo apt install -y g++-aarch64-linux-gnu echo -e "\n\n[target.aarch64-unknown-linux-gnu]\nlinker = \"aarch64-linux-gnu-gcc\"" >> .cargo/config.toml - uses: Swatinem/rust-cache@v2 - run: cargo build --release working-directory: ./server - run: cargo build --release --target aarch64-unknown-linux-gnu working-directory: ./server env: BINDGEN_EXTRA_CLANG_ARGS: --sysroot /usr/aarch64-linux-gnu - uses: actions/upload-artifact@v3 with: name: oxigraph_server_x86_64_linux_gnu path: target/release/oxigraph_server - uses: actions/upload-artifact@v3 with: name: oxigraph_server_aarch64-linux_gnu path: target/aarch64-unknown-linux-gnu/release/oxigraph_server - run: mv target/release/oxigraph_server oxigraph_server_${{ github.event.release.tag_name }}_x86_64_linux_gnu if: github.event_name == 'release' - run: mv target/aarch64-unknown-linux-gnu/release/oxigraph_server oxigraph_server_${{ github.event.release.tag_name }}_aarch64_linux_gnu if: github.event_name == 'release' - uses: softprops/action-gh-release@v1 with: files: | oxigraph_server_${{ github.event.release.tag_name }}_x86_64_linux_gnu oxigraph_server_${{ github.event.release.tag_name }}_aarch64_linux_gnu if: github.event_name == 'release' binary_mac: runs-on: macos-latest env: DEVELOPER_DIR: '/Applications/Xcode.app/Contents/Developer' SDKROOT: '/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk' MACOSX_DEPLOYMENT_TARGET: '10.14' steps: - uses: actions/checkout@v3 with: submodules: true - run: rustup update && rustup target add aarch64-apple-darwin - uses: Swatinem/rust-cache@v2 - run: cargo build --release working-directory: ./server - run: cargo build --release --target aarch64-apple-darwin working-directory: ./server - uses: actions/upload-artifact@v3 with: name: oxigraph_server_x86_64_apple path: target/release/oxigraph_server - uses: actions/upload-artifact@v3 with: name: oxigraph_server_aarch64_apple path: target/aarch64-apple-darwin/release/oxigraph_server - run: mv target/release/oxigraph_server oxigraph_server_${{ github.event.release.tag_name }}_x86_64_apple if: github.event_name == 'release' - run: mv target/aarch64-apple-darwin/release/oxigraph_server oxigraph_server_${{ github.event.release.tag_name }}_aarch64_apple if: github.event_name == 'release' - uses: softprops/action-gh-release@v1 with: files: | oxigraph_server_${{ github.event.release.tag_name }}_x86_64_apple oxigraph_server_${{ github.event.release.tag_name }}_aarch64_apple if: github.event_name == 'release' binary_windows: runs-on: windows-latest steps: - uses: actions/checkout@v3 with: submodules: true - run: rustup update - uses: Swatinem/rust-cache@v2 - run: Remove-Item -LiteralPath "C:\msys64\" -Force -Recurse - run: cargo build --release working-directory: ./server - uses: actions/upload-artifact@v3 with: name: oxigraph_server_x86_64_windows_msvc path: target/release/oxigraph_server.exe - run: mv target/release/oxigraph_server.exe oxigraph_server_${{ github.event.release.tag_name }}_x86_64_windows_msvc.exe if: github.event_name == 'release' - uses: softprops/action-gh-release@v1 with: files: oxigraph_server_${{ github.event.release.tag_name }}_x86_64_windows_msvc.exe if: github.event_name == 'release' python_sdist: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: submodules: true - run: rustup update - uses: Swatinem/rust-cache@v2 - uses: actions/setup-python@v4 with: python-version: "3.12" cache: pip cache-dependency-path: '**/requirements.dev.txt' - run: pip install -r python/requirements.dev.txt - run: maturin build -m python/Cargo.toml - run: pip install --no-index --find-links=target/wheels/ pyoxigraph - run: rm -r target/wheels - run: python generate_stubs.py pyoxigraph pyoxigraph.pyi --black working-directory: ./python - run: maturin sdist -m python/Cargo.toml - uses: actions/upload-artifact@v3 with: name: pyoxigraph_source path: target/wheels/*.tar.gz - run: pip install twine && twine upload target/wheels/* env: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} if: github.event_name == 'release' wheel_linux: runs-on: ubuntu-latest strategy: matrix: architecture: [ "x86_64", "aarch64" ] continue-on-error: true steps: - uses: actions/checkout@v3 with: submodules: true - uses: docker/setup-qemu-action@v2 with: platforms: linux/${{ matrix.architecture }} if: github.event_name == 'release' && matrix.architecture != 'x86_64' - run: sed 's/%arch%/${{ matrix.architecture }}/g' .github/workflows/manylinux_build.sh | sed 's/%for_each_version%/${{ github.event_name == 'release' || '' }}/g' > .github/workflows/manylinux_build_script.sh - run: docker run -v "$(pwd)":/workdir --platform linux/${{ matrix.architecture }} quay.io/pypa/manylinux2014_${{ matrix.architecture }} /bin/bash /workdir/.github/workflows/manylinux_build_script.sh if: github.event_name == 'release' || matrix.architecture == 'x86_64' - uses: actions/upload-artifact@v3 with: name: pyoxigraph_wheel_x86_64_linux path: target/wheels/*.whl - uses: pypa/gh-action-pypi-publish@release/v1 with: user: __token__ password: ${{ secrets.PYPI_PASSWORD }} packages-dir: target/wheels if: github.event_name == 'release' wheel_linux_musl: runs-on: ubuntu-latest strategy: matrix: architecture: [ "x86_64", "aarch64" ] continue-on-error: true steps: - uses: actions/checkout@v3 with: submodules: true - uses: docker/setup-qemu-action@v2 with: platforms: linux/${{ matrix.architecture }} if: github.event_name == 'release' && matrix.architecture != 'x86_64' - run: sed 's/%arch%/${{ matrix.architecture }}/g' .github/workflows/musllinux_build.sh | sed 's/%for_each_version%/${{ github.event_name == 'release' || '' }}/g' > .github/workflows/musllinux_build_script.sh - run: docker run -v "$(pwd)":/workdir --platform linux/${{ matrix.architecture }} quay.io/pypa/musllinux_1_1_${{ matrix.architecture }} /bin/bash /workdir/.github/workflows/musllinux_build_script.sh if: github.event_name == 'release' || matrix.architecture == 'x86_64' - uses: actions/upload-artifact@v3 with: name: pyoxigraph_wheel_x86_64_linux_musl path: target/wheels/*.whl - uses: pypa/gh-action-pypi-publish@release/v1 with: user: __token__ password: ${{ secrets.PYPI_PASSWORD }} packages-dir: target/wheels if: github.event_name == 'release' wheel_mac: runs-on: macos-latest env: DEVELOPER_DIR: '/Applications/Xcode.app/Contents/Developer' SDKROOT: '/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk' MACOSX_DEPLOYMENT_TARGET: '10.14' steps: - uses: actions/checkout@v3 with: submodules: true - run: rustup update && rustup target add aarch64-apple-darwin - uses: Swatinem/rust-cache@v2 - uses: actions/setup-python@v4 with: python-version: "3.10" cache: pip cache-dependency-path: '**/requirements.dev.txt' - run: pip install -r python/requirements.dev.txt - run: maturin build --release -m python/Cargo.toml --features abi3 - run: pip install --no-index --find-links=target/wheels/ pyoxigraph - run: rm -r target/wheels - run: python generate_stubs.py pyoxigraph pyoxigraph.pyi --black working-directory: ./python - run: maturin build --release --target universal2-apple-darwin -m python/Cargo.toml --features abi3 - run: maturin build --release -m python/Cargo.toml --features abi3 if: github.event_name == 'release' - run: maturin build --release --target aarch64-apple-darwin -m python/Cargo.toml --features abi3 if: github.event_name == 'release' - uses: actions/upload-artifact@v3 with: name: pyoxigraph_wheel_universal2_mac path: target/wheels/*.whl - run: pip install twine && twine upload target/wheels/* env: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} if: github.event_name == 'release' wheel_windows: runs-on: windows-latest steps: - uses: actions/checkout@v3 with: submodules: true - run: rustup update - uses: Swatinem/rust-cache@v2 - uses: actions/setup-python@v4 with: python-version: "3.10" cache: pip cache-dependency-path: '**/requirements.dev.txt' - run: Remove-Item -LiteralPath "C:\msys64\" -Force -Recurse - run: pip install -r python/requirements.dev.txt - run: maturin build --release -m python/Cargo.toml --features abi3 - run: pip install --no-index --find-links=target/wheels/ pyoxigraph - run: rm -r target/wheels - run: python generate_stubs.py pyoxigraph pyoxigraph.pyi --black working-directory: ./python - run: maturin build --release -m python/Cargo.toml --features abi3 - uses: actions/upload-artifact@v3 with: name: pyoxigraph_wheel_x86_64_windows path: target/wheels/*.whl - run: pip install twine && twine upload target/wheels/* env: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} if: github.event_name == 'release' npm_tarball: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: submodules: true - run: rustup update - uses: Swatinem/rust-cache@v2 - run: cargo install wasm-pack || true - uses: actions/setup-node@v3 with: node-version: 16 cache: npm cache-dependency-path: "js/package.json" registry-url: https://registry.npmjs.org - run: npm run pack working-directory: ./js - uses: actions/upload-artifact@v3 with: name: oxigraph_wasm_npm path: js/*.tgz - run: npm run release working-directory: ./js env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} if: github.event_name == 'release' docker: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: submodules: true - uses: docker/setup-buildx-action@v2 - uses: docker/login-action@v2 with: registry: ghcr.io username: ${{github.actor}} password: ${{secrets.GITHUB_TOKEN}} - uses: docker/login-action@v2 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} if: github.event_name == 'release' - uses: docker/metadata-action@v4 id: docker_meta with: images: | ${{ github.repository }},enable=${{ github.event_name == 'release' }} ghcr.io/${{ github.repository }} - uses: docker/build-push-action@v4 with: context: . file: server/Dockerfile platforms: linux/amd64,linux/arm64 pull: true push: true tags: ${{ steps.docker_meta.outputs.tags }} labels: ${{ steps.docker_meta.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=max publish_crates: if: github.event_name == 'release' runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: submodules: true - run: rustup update - run: cargo login $CRATES_IO_TOKEN env: CRATES_IO_TOKEN: ${{ secrets.CRATES_IO_TOKEN }} - run: cargo publish working-directory: ./oxrocksdb-sys continue-on-error: true - run: cargo publish working-directory: ./lib/oxsdatatypes continue-on-error: true - run: cargo publish working-directory: ./lib/oxrdf continue-on-error: true - run: cargo publish working-directory: ./lib/sparesults continue-on-error: true - run: cargo publish working-directory: ./lib/spargebra continue-on-error: true - run: cargo publish working-directory: ./lib/sparql-smith continue-on-error: true - run: cargo publish working-directory: ./lib continue-on-error: true - run: cargo publish working-directory: ./server homebrew: if: "github.event_name == 'release' && !contains('-', github.event.release.tag_name)" runs-on: ubuntu-latest needs: full_archive steps: - uses: actions/checkout@v3 with: repository: oxigraph/homebrew-oxigraph token: ${{ secrets.FULL_ACCESS_TOKEN }} - run: | wget "https://github.com/oxigraph/oxigraph/releases/download/${{ github.event.release.tag_name }}/oxigraph_${{ github.event.release.tag_name }}.tar.gz" SHA=`shasum -a 256 "oxigraph_${{ github.event.release.tag_name }}.tar.gz" | awk '{ print $1 }'` rm "oxigraph_${{ github.event.release.tag_name }}.tar.gz" sed -i "s/download\/.*\.tar/download\/${{ github.event.release.tag_name }}\/oxigraph_${{ github.event.release.tag_name }}.tar/g" Formula/oxigraph.rb sed -i "s/sha256 \".*\"/sha256 \"$SHA\"/g" Formula/oxigraph.rb git config user.name github-actions git config user.email github-actions@github.com git add . git diff-index --quiet HEAD || git commit -m "Upgrades to ${{ github.event.release.tag_name }}" git push full_archive: if: github.event_name == 'release' runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: submodules: true - run: | rm -rf .git bench fuzz zip -r oxigraph_${{ github.event.release.tag_name }}.zip . tar -czf /tmp/oxigraph_${{ github.event.release.tag_name }}.tar.gz . mv /tmp/oxigraph_${{ github.event.release.tag_name }}.tar.gz . - uses: softprops/action-gh-release@v1 with: files: | oxigraph_${{ github.event.release.tag_name }}.zip oxigraph_${{ github.event.release.tag_name }}.tar.gz oxigraph-0.3.22/.github/workflows/manylinux_build.sh000066400000000000000000000020471453236674100225710ustar00rootroot00000000000000cd /workdir yum -y install centos-release-scl-rh yum -y install llvm-toolset-7.0 source scl_source enable llvm-toolset-7.0 curl https://static.rust-lang.org/rustup/dist/%arch%-unknown-linux-gnu/rustup-init --output rustup-init chmod +x rustup-init ./rustup-init -y --profile minimal source "$HOME/.cargo/env" export PATH="${PATH}:/opt/python/cp37-cp37m/bin:/opt/python/cp38-cp38/bin:/opt/python/cp39-cp39/bin:/opt/python/cp310-cp310/bin:/opt/python/cp311-cp311/bin" cd python python3.10 -m venv venv source venv/bin/activate pip install -r requirements.dev.txt maturin develop --release -m Cargo.toml python generate_stubs.py pyoxigraph pyoxigraph.pyi --black maturin build --release -m Cargo.toml --features abi3 --compatibility manylinux2014 if [ %for_each_version% ]; then for VERSION in 7 8 9 10 11 12; do maturin build --release -m Cargo.toml --interpreter "python3.$VERSION" --compatibility manylinux2014 done for VERSION in 9 10; do maturin build --release -m Cargo.toml --interpreter "pypy3.$VERSION" --compatibility manylinux2014 done fi oxigraph-0.3.22/.github/workflows/musllinux_build.sh000066400000000000000000000015031453236674100226010ustar00rootroot00000000000000cd /workdir apk add clang-dev curl https://static.rust-lang.org/rustup/dist/%arch%-unknown-linux-musl/rustup-init --output rustup-init chmod +x rustup-init ./rustup-init -y --profile minimal source "$HOME/.cargo/env" export PATH="${PATH}:/opt/python/cp37-cp37m/bin:/opt/python/cp38-cp38/bin:/opt/python/cp39-cp39/bin:/opt/python/cp310-cp310/bin:/opt/python/cp311-cp311/bin" cd python python3.10 -m venv venv source venv/bin/activate pip install -r requirements.dev.txt maturin develop --release -m Cargo.toml python generate_stubs.py pyoxigraph pyoxigraph.pyi --black maturin build --release -m Cargo.toml --features abi3 --compatibility musllinux_1_1 if [ %for_each_version% ]; then for VERSION in 7 8 9 10 11 12; do maturin build --release -m Cargo.toml --interpreter "python3.$VERSION" --compatibility musllinux_1_1 done fi oxigraph-0.3.22/.github/workflows/tests.yml000066400000000000000000000306431453236674100207220ustar00rootroot00000000000000name: Change tests on: pull_request: branches: - main schedule: - cron: "12 3 * * *" concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: fmt: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - run: rustup update && rustup component add rustfmt - run: cargo fmt -- --check clippy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: submodules: true - run: rustup update && rustup component add clippy - uses: Swatinem/rust-cache@v2 - run: cargo clippy working-directory: ./lib/oxsdatatypes - run: cargo clippy working-directory: ./lib/oxrdf - run: cargo clippy working-directory: ./lib/sparesults - run: cargo clippy working-directory: ./lib/spargebra - run: cargo clippy --all-targets --all-features clippy_wasm_js: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: submodules: true - run: rustup update && rustup target add wasm32-unknown-unknown && rustup component add clippy - uses: Swatinem/rust-cache@v2 - run: cargo clippy --lib --tests --target wasm32-unknown-unknown working-directory: ./js clippy_wasi: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: submodules: true - run: rustup update && rustup target add wasm32-wasi && rustup component add clippy - uses: Swatinem/rust-cache@v2 - run: cargo clippy --lib --tests --target wasm32-wasi working-directory: ./lib clippy_msv: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: submodules: true - run: rustup update && rustup override set 1.60.0 && rustup component add clippy - uses: Swatinem/rust-cache@v2 - run: cargo clippy -- -D warnings -D clippy::all working-directory: ./lib/oxsdatatypes - run: cargo clippy -- -D warnings -D clippy::all working-directory: ./lib/oxrdf - run: cargo clippy -- -D warnings -D clippy::all working-directory: ./lib/sparesults - run: cargo clippy -- -D warnings -D clippy::all working-directory: ./lib/spargebra - run: cargo clippy --all-targets -- -D warnings -D clippy::all working-directory: ./server clippy_msv_wasm_js: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: submodules: true - run: rustup update && rustup override set 1.60.0 && rustup target add wasm32-unknown-unknown && rustup component add clippy - uses: Swatinem/rust-cache@v2 - run: cargo clippy --lib --tests --target wasm32-unknown-unknown -- -D warnings -D clippy::all working-directory: ./js clippy_msv_wasi: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: submodules: true - run: rustup update && rustup override set 1.60.0 && rustup target add wasm32-wasi && rustup component add clippy - uses: Swatinem/rust-cache@v2 - run: cargo clippy --lib --tests --target wasm32-wasi -- -D warnings -D clippy::all working-directory: ./lib deny: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - run: rustup update - uses: Swatinem/rust-cache@v2 - run: cargo install cargo-deny || true - run: cargo deny check semver_checks: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: submodules: true - run: rustup update - uses: Swatinem/rust-cache@v2 - run: cargo install cargo-semver-checks || true - run: cargo semver-checks check-release --exclude oxrocksdb-sys --exclude oxigraph_js --exclude pyoxigraph --exclude oxigraph_testsuite --exclude oxigraph_server test_linux: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: submodules: true - run: rustup update - uses: Swatinem/rust-cache@v2 - run: cargo test --all-features env: RUST_BACKTRACE: 1 test_linux_latest: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: submodules: true - run: rustup update - uses: Swatinem/rust-cache@v2 - run: rm Cargo.lock && cargo update - run: cargo test address_sanitizer: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: submodules: true - run: rustup update && rustup override set nightly - run: sudo apt install -y llvm - uses: Swatinem/rust-cache@v2 - run: cargo test --tests --target x86_64-unknown-linux-gnu --workspace --exclude pyoxigraph --exclude oxigraph_testsuite --exclude oxigraph_server env: RUST_BACKTRACE: 1 RUSTFLAGS: -Z sanitizer=address test_windows: runs-on: windows-latest steps: - uses: actions/checkout@v3 with: submodules: true - run: rustup update - uses: Swatinem/rust-cache@v2 - run: Remove-Item -LiteralPath "C:\msys64\" -Force -Recurse - run: cargo test --all-features env: RUST_BACKTRACE: 1 test_wasi: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: submodules: true - run: rustup update && rustup target add wasm32-wasi - uses: Swatinem/rust-cache@v2 - uses: taiki-e/install-action@wasmtime - run: cargo install cargo-wasi || true - run: cargo wasi test --workspace --exclude oxigraph_js --exclude oxigraph_server --exclude oxigraph_testsuite --exclude oxrocksdb-sys --exclude pyoxigraph env: RUST_BACKTRACE: 1 rustdoc: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: submodules: true - run: rustup update - uses: Swatinem/rust-cache@v2 - run: cargo doc --all-features working-directory: ./lib rustdoc_msrv: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: submodules: true - run: rustup update && rustup override set 1.60.0 - uses: Swatinem/rust-cache@v2 - run: cargo doc --all-features working-directory: ./lib env: RUSTDOCFLAGS: -D warnings js: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - run: rustup update - uses: Swatinem/rust-cache@v2 - run: cargo install wasm-pack || true - uses: actions/setup-node@v3 with: node-version: 16 cache: npm cache-dependency-path: "js/package.json" - run: npm install working-directory: ./js - run: npm test working-directory: ./js python: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: submodules: true - run: rustup update - uses: Swatinem/rust-cache@v2 - uses: actions/setup-python@v4 with: python-version: "3.10" cache: pip cache-dependency-path: '**/requirements.dev.txt' - run: pip install -r python/requirements.dev.txt - run: python -m black --check --diff --color . working-directory: ./python - run: maturin build -m python/Cargo.toml - run: pip install --no-index --find-links=target/wheels/ pyoxigraph - run: rm -r target/wheels - run: python -m unittest working-directory: ./python/tests - run: sphinx-build -M doctest . build working-directory: ./python/docs - run: sphinx-build -M html . build working-directory: ./python/docs - run: python generate_stubs.py pyoxigraph pyoxigraph.pyi --black working-directory: ./python - run: python -m mypy.stubtest pyoxigraph --allowlist=mypy_allowlist.txt working-directory: ./python - run: python -m mypy generate_stubs.py tests --strict working-directory: ./python - run: python -m ruff check . working-directory: ./python python_msv: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: submodules: true - run: rustup update - uses: Swatinem/rust-cache@v2 - uses: actions/setup-python@v4 with: python-version: "3.7" cache: pip cache-dependency-path: '**/requirements.dev.txt' - run: pip install -r python/requirements.dev.txt - run: maturin build -m python/Cargo.toml - run: pip install --no-index --find-links=target/wheels/ pyoxigraph - run: rm -r target/wheels - run: python -m unittest working-directory: ./python/tests python_windows: runs-on: windows-latest steps: - uses: actions/checkout@v3 with: submodules: true - run: rustup update - uses: Swatinem/rust-cache@v2 - uses: actions/setup-python@v4 with: python-version: "3.10" cache: pip cache-dependency-path: '**/requirements.dev.txt' - run: pip install "maturin~=1.0" - run: maturin build -m python/Cargo.toml - run: pip install --no-index --find-links=target/wheels/ pyoxigraph - run: rm -r target/wheels - run: python -m unittest working-directory: ./python/tests typos: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 - run: cargo install typos-cli || true - run: typos clang_fmt: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - run: sudo apt install -y clang-format - run: clang-format --Werror --dry-run oxrocksdb-sys/api/* fuzz_changes: if: github.event_name == 'pull_request' runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: submodules: true - uses: google/clusterfuzzlite/actions/build_fuzzers@v1 with: language: rust github-token: ${{ secrets.GITHUB_TOKEN }} sanitizer: address storage-repo: https://${{ secrets.FULL_ACCESS_TOKEN }}@github.com/oxigraph/clusterfuzzlite-oxigraph.git - uses: google/clusterfuzzlite/actions/run_fuzzers@v1 with: github-token: ${{ secrets.GITHUB_TOKEN }} fuzz-seconds: 600 mode: code-change sanitizer: address minimize-crashes: true parallel-fuzzing: true storage-repo: https://${{ secrets.FULL_ACCESS_TOKEN }}@github.com/oxigraph/clusterfuzzlite-oxigraph.git fuzz_repo: if: github.event_name != 'pull_request' runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: submodules: true - uses: google/clusterfuzzlite/actions/build_fuzzers@v1 with: language: rust github-token: ${{ secrets.GITHUB_TOKEN }} sanitizer: address - uses: google/clusterfuzzlite/actions/run_fuzzers@v1 with: github-token: ${{ secrets.GITHUB_TOKEN }} fuzz-seconds: 3600 mode: batch sanitizer: address minimize-crashes: true parallel-fuzzing: true storage-repo: https://${{ secrets.FULL_ACCESS_TOKEN }}@github.com/oxigraph/clusterfuzzlite-oxigraph.git continue-on-error: true - uses: google/clusterfuzzlite/actions/run_fuzzers@v1 with: github-token: ${{ secrets.GITHUB_TOKEN }} fuzz-seconds: 3600 mode: prune storage-repo: https://${{ secrets.FULL_ACCESS_TOKEN }}@github.com/oxigraph/clusterfuzzlite-oxigraph.git continue-on-error: true fuzz_coverage: if: github.event_name != 'pull_request' needs: fuzz_repo runs-on: ubuntu-latest steps: - uses: google/clusterfuzzlite/actions/build_fuzzers@v1 with: language: rust sanitizer: coverage - uses: google/clusterfuzzlite/actions/run_fuzzers@v1 with: github-token: ${{ secrets.GITHUB_TOKEN }} fuzz-seconds: 3600 mode: coverage sanitizer: coverage storage-repo: https://${{ secrets.FULL_ACCESS_TOKEN }}@github.com/oxigraph/clusterfuzzlite-oxigraph.git shellcheck: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - run: sudo apt install -y shellcheck - run: git grep -l '^#\( *shellcheck \|!\(/bin/\|/usr/bin/env \)\(sh\|bash\|dash\|ksh\)\)' | xargs shellcheck spec_links: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - run: python test_spec_links.py oxigraph-0.3.22/.gitignore000066400000000000000000000002361453236674100154230ustar00rootroot00000000000000**/target **/*.rs.bk Cargo.lock .idea *.iml js/node_modules lib/tests/rocksdb_bc_data venv .env data/ .htpasswd **/docs/_build **/docs/build *.so *.pyc **.pyioxigraph-0.3.22/.gitmodules000066400000000000000000000010071453236674100156050ustar00rootroot00000000000000[submodule "testsuite/rdf-tests"] path = testsuite/rdf-tests url = https://github.com/w3c/rdf-tests.git [submodule "testsuite/rdf-star"] path = testsuite/rdf-star url = https://github.com/w3c/rdf-star.git [submodule "bench/bsbm-tools"] path = bench/bsbm-tools url = https://github.com/Tpt/bsbm-tools.git [submodule "oxrocksdb-sys/rocksdb"] path = oxrocksdb-sys/rocksdb url = https://github.com/oxigraph/rocksdb.git [submodule "oxrocksdb-sys/lz4"] path = oxrocksdb-sys/lz4 url = https://github.com/lz4/lz4.git oxigraph-0.3.22/.mailmap000066400000000000000000000002731453236674100150550ustar00rootroot00000000000000Thomas Tanon Thomas Tanon Thomas Tanon oxigraph-0.3.22/.readthedocs.yaml000066400000000000000000000004141453236674100166600ustar00rootroot00000000000000version: 2 sphinx: builder: html build: os: "ubuntu-22.04" tools: python: "3" rust: "1.64" apt_packages: - clang python: install: - requirements: python/requirements.dev.txt - method: pip path: python submodules: include: all oxigraph-0.3.22/CHANGELOG.md000066400000000000000000000602601453236674100152470ustar00rootroot00000000000000## [0.3.22] - 2023-11-29 ### Changed - Allows to compile with more recent `bindgen` and `cc` - Fixes compatibility with `spin_no_std` feature of `lazy_static` ## [0.3.21] - 2023-11-29 ### Changed - Bulk loader: do not fail when loading empty files. - Python: fixes source distribution. - Upgrades RocksDB to 7.8.1. ## [0.3.20] - 2023-10-23 ### Changed - SPARQL: fixes `STR` evaluation on small IRI (less than 16 bytes) that was broken. - SPARQL update: fixes `WHERE` clause evaluation that was generating too many solutions in some cases. - Upgrades RocksDB to 8.7.1. ## [0.3.19] - 2023-08-18 ### Added - Python: allows to give `pathlib.Path` argument when a path is expected. - Cargo.toml: add a documentation field to link to docs.rs documentation. ### Changed - Upgrades RocksDB to 8.3.2. ## [0.3.18] - 2023-06-13 ### Changed - SPARQL: fixes evaluation of `||` when all alternatives are `false`. The results must be `false` and not an error. - SPARQL: `xsd:duration` it is now possible to properly parse and serialize all numbers that can be internally represented by the encoding used by Oxigraph. - Python: fixes `Store.contains_named_graph` return type annotation. ## [0.3.17] - 2023-06-11 ### Added - SPARQL: support of `xsd:duration` to SPARQL `SUM` aggregate function. - Server: support for systemd "notify" service option. - Server: uses the target graph name as base URI when `POST`ing and `PUT`ing data. - Python: `Store.contains_named_graph` method. ### Changed - SPARQL: `xsd:decimal` multiplication and division have been improved to avoid raising overflow because of internal operations in some cases. - SPARQL: `xsd:decimal` parser is now able to properly parse all numbers that can be internally represented by the encoding used by Oxigraph. - SPARQL: `xsd:decimal` avoids bad overflow on unary `-` operator. - SPARQL: reduces loss of precision when casting `xsd:decimal` to `xsd:float` or `xsd:double`. - SPARQL: improves a bit the AST in case of a lot of `&&`, `||` or `IN` operators. - SPARQL: fixes some optimization bugs around `MINUS` inside `OPTIONAL`. - SPARQL: makes for loop join choice instead of hash join a bit more aggressive. - Avoids random crashes when building RocksDB for aarch64. - Python: fixes support of text I/O with not-ASCII char. - Python: upgrades PyO3 to 0.19. - `spargebra`: `GroundTermPattern::Triple` is now properly gated behind the `"rdf-star"` feature. - `oxsdatatypes`: Deprecates `is_naan` that is renamed to `is_nan` (we like bread but prefer numbers). - `oxsdatatypes`: Adds `checked_neg` methods on numerical types. - `oxsdatatypes`: Drops `nom` dependency and uses hand-written parsers instead. ## [0.3.16] - 2023-04-29 ### Changed - Fixes flush and compaction on the GSPO index. It might improve Oxigraph performances and storage space. - SPARQL: fixes some optimizations in presence quoted triples with nested variables. - SPARQL profiler: adds EXISTS operation to the explanation and profiling tree. - Upgrades RocksDB to 8.1.1. ## [0.3.15] - 2023-04-18 ### Added - Rust: adds `Store.explain_query_opt` method that allows to get an explanation of the evaluation with profiling statistics. - Server: adds explanation and profiling to the `query` action (`--explain`, `--explain-file` and `--stats` options). - Python: implements the `__match_args__` attribute on terms (literals, triples, quads...) to allow `match` operator usage. - Server: adds the `--cors` option to the `serve` actions to allow cross-origin resource sharing. ### Changed - SPARQL: fixes evaluation of empty aggregation without GROUP BY: aggregators now return their default value (0 for COUNT...) and not an empty row. - SPARQL: fixes parsing of decimal with more than 19 digits in the fractional part. - Server docker image: switch to the smaller distroless base images. - Bulk loader: by default only uses 2 concurrent threads and around 2GB of RAM. - Server load: progress is now printed to stderr much more regularly. ## [0.3.14] - 2023-03-19 ### Added - Read only and secondary RocksDB storage. Allows to open the data as read-only or to follow a primary instance. - Server: adds multiple commands: - `serve-secondary` and `serve-read-only` to serve the HTTP server in secondary and read-only modes. - `dump` to dump the database content to a file. - `query` and `update` to execute SPARQL query and updates. - `backup` to do a database backup. - `optimize` to optimize the database storage. - Server: adds `format` and `graph` options to the `load` command in order to select the loaded data format and the target graph. - Python: `Store.extend` and `Store.bulk_extend` methods. - Python: allows to pickle basic data model classes. ### Changed - Upgrades RocksDB to 8.0.0. - Server: listening to localhost now properly listen to both IPv4 and IPv6. - RDF/XML and XML parser results: avoid an ever growing buffer. - JSON SPARQL results: allows the "head" key to be at the end of the document. - TSV SPARQL results: properly quote `\t` and print trailing line jumps. - `Term::from_str`: fixes parsing of blank nodes in object position of quoted triples. - `QuerySolution`: implements `Eq` and `Debug`. - JS: Reduces WASM build size. - OxRDF: fixes `Graph` and `Dataset` serialization to output proper N-Triples and N-Quads. ## [0.3.13] - 2023-02-23 ### Changed - Fixes serialization of times with a decimal number of seconds lower than 10 (now `01:01:01.01` and not `01:01:1.01`). - Turtle and TriG: fixes parsing for prefixes named after keywords (`prefix`, `base`, `graph`, `true` and `false`). ## [0.3.12] - 2023-02-18 ### Added - `From` for `GraphName` (and similarly for `*Ref`). - Prebuilt Python wheels for Linux with [musl libc](https://www.musl-libc.org/). ### Changed - Fixes TriG serialization. - `QueryDataset` is now properly exposed in the public Rust API. ## [0.3.11] - 2023-01-18 ### Added - SPARQL: Implementation of the `LATERAL` operator following [SPARQL SEP-0006](https://github.com/w3c/sparql-12/blob/main/SEP/SEP-0006/sep-0006.md). Support is behind the `sep-0006` feature in `spargebra` and enabled by default in Oxigraph. - SPARQL: Implementation of the `ADJUST` function following [SPARQL SEP-0002](https://github.com/w3c/sparql-12/blob/main/SEP/SEP-0002/sep-0002.md). Support is behind the `sep-0002` feature in `spargebra` and enabled by default in Oxigraph. - Rust: There is a new stand-alone crate `oxsdatatypes` implementing Rust structs for the common XML schema datatypes. It was part of the Oxigraph crate and it might be useful for other SPARQL or XPath implementations. - Rust: The `oxigraph` crate can now be compiled for `wasm32-wasi` with the basic in-memory backend but without RocksDB. ### Changed - SPARQL: The property path evaluator was sometime emitting duplicates when evaluating disjunctive patterns (`a|b`). It is now fixed. - SPARQL: If written explicitly in the SPARQL query, the regular expressions are now compiled once and not for each row. - SPARQL: Property path evaluation with both start and end variables bound has been optimized. - SPARQL: Casts to `xsd:decimal` from `xsd:float` and `xsd:double` now properly fails on overflow instead of overflowing the internal 128-bits representation. This follows [XPath casting rules](https://www.w3.org/TR/xpath-functions-31/#casting-to-decimal). - Rust: The minimal supported Rust version is set at 1.60 and enforced using the CI. - Python: Local builds will now target the specific Python version instead of [abi3](https://docs.python.org/3/c-api/stable.html). abi3 wheels are still released on Pypi alongside new Python-version specific builds for Linux+GNU. - SPARQL: Fixes a panic when the estimated upper bound of the results size was overflowing a `usize`. - Python: Uses `typing.IO` in Python stubs instead of narrower interfaces. - Upgrades RocksDB to 7.9.2, `quick-xml` to 0.27 and `pyo3` to 0.18. ## [0.3.10] - 2022-12-21 ### Added - SPARQL: Property path with unbound graph are now evaluated. For example, `SELECT * WHERE { GRAPH ?g { ?s ex:p+ ?o } }` now works. - SPARQL: The query optimizer is now fuzzed for better testing. ### Changed - SPARQL: Evaluation of zero-length paths with both start and end unbounded now return only terms defined in the current graph but not terms only defined in the query. For example, in `SELECT * WHERE { VALUES ?s { 1 } { ?s ex:p? ?o } }` the literal `1` won't be returned anymore if not in the queried graph. - Python: type stubs are now compatible with Python 3.7 and Mypy strict mode. - RDF/XML: allows entities declared using other entities. - Upgrades `quick-xml` to 0.26. ## [0.3.9] - 2022-12-07 ### Added - Server: The `/store` endpoints now has a `no_transaction` HTTP option for `POST` and `PUT` request to get better performances at the cost of transactional guarantees. - Server: The `/store` endpoints now has a `lenient` HTTP option for `POST` and `PUT` request to ignore syntax errors (requires the `no_transaction` option). - Server: allows path that are not valid UTF-8 in file path CLI arguments. - Rust: `From` to `oxigraph::Query` (thanks to @hobofan). ### Changed - SPARQL: `NOW()` function properly returns the current time and not 1970-01-01 - SPARQL: fixes serialization of SPARQL queries (property path and STRSTARTS function). - SPARQL: slightly optimize aggregates by avoiding an unneeded projection. - SPARQL: the parser now cleanly fails if invalid `VALUES` clauses are provided. - SPARQL: In DELETE/INSERT UPDATE the currently written values can't be read anymore ("Halloween problem"). - `oxrdf`: makes Clippy run without warnings when `rdf-star` is disable. - Python: makes type annotations compatible with Python 3.7. - Python: makes sure the parameter default value is always included in the type annotation. ## [0.3.8] - 2022-10-22 ### Changed - Python: avoid uploading debug wheels to pypi. ## [0.3.7] - 2022-10-22 ### Added - Python type stubs are now generated and distributed alongside wheels. ### Changed - SPARQL: Fixes evaluation of sub queries in which some variables might not be always bound. - Python: Uses https://pyoxigraph.readthedocs.io instead of https://oxigraph.org/pyoxigraph/ to store pyoxigraph documentation. - Server: Migration to Clap v4. Slight changes to the console textual outputs. ## [0.3.6] - 2022-08-16 ### Changed - Server: Makes sure body is always sent for all HTTP response codes that are not explicitly to not do that according to the HTTP specification. - Python: Adds support of reading from `io.TextIOBase`. ## [0.3.5] - 2022-08-02 ### Changed - Fixes a bug in the SPARQL parser with nested anonymous blank nodes (`[]`). - Migrates the Python documentation skin to [Furo](https://pradyunsg.me/furo/). ## [0.3.4] - 2022-07-17 ### Changed - Allows multiple value to be given to `oxigraph_server` `--file` parameter. - Limits parallelism of `oxigraph_server` file loader to avoid stack overflows. ## [0.3.3] - 2022-06-12 ### Added - `QueryResults::with_http_redirection_limit` that allows to set a limit on the number of HTTP redirection followed (`0` by default). ### Changed - Fixes a bug in SPARQL parser that was always enabling the `SILENT` option of the `SERVICE` operator. - Allows unknown keys in the objects present in the SPARQL JSON query results. It allows to parse e.g. Virtuoso query results. - Allows `"typed-literal"` as an alias of `"literal"` in SPARQL JSON query results. - Improves the HTTP client error reporting: no silent failures on 4XX and 5XX responses. - Upgrades RocksDB to 7.3.1. - Upgrades quick-xml to 0.23. ## [0.3.2] - 2022-04-24 ### Changed - Fixes a bug in the server bulk loader that crashed on very small files. - Upgrades RocksDB to v7.1. - Removes some dead code in the bulk loader. ## [0.3.1] - 2022-04-02 ### Changed - The default git branch is now `main` and not `master` (thanks to @nyurik). - Upgrades RocksDB to v7.0.4. - Limits the number of bulk loader threads to at most 4 (allows bigger BTree chunks and a better data layout). - Limits the number of files opened by RocksDB to the soft file descriptor limit minus 48. ## [0.3.0] - 2022-03-19 ### Changed - Fixes compilation on ARM. - Moves some lints from errors to warnings in order to avoid compilation failures on different Rust versions. ## [0.3.0-rc.1] - 2022-03-14 ### Added - The bulk loader now checks available memory and tries to increase its batch size to make use of it. - The Bulk loader provides now a `--lenient` option to keep loading a file even if invalid data is found (works only with N-Triples and N-Quads). This behavior can be customised in the Rust API using the `BulkLoader::on_parse_error` method. ### Changed - Rocksdb has been upgrade to 7.0.2. It now requires a C++17 compatible compiler. This required dropping support of macOS 10.9 to 10.13. ## [0.3.0-beta.4] - 2022-02-27 ### Added - JS: Oxigraph NPM package is now also supporting web browsers and WebPack. - JS: RDF term related classes now overrides the `toString` method. - Python: It is now possible to directly give a file path to the `parse`, `serialize`, `Store.load`, `Store.bulk_load` and `Store.dump` functions. - Python: New `Store.clear_graph`, `Store.clear`, `Store.optimize` and `Store.flush` methods. ### Removed - `sophia_api` traits implementation following a request of Sophia maintainer. ### Changed - SPARQL: fixes evaluation of SPARQL queries with no results but an `ORDER BY` clause. There should be no group in the output instead of one empty group. This behavior has been changed following [this discussion](https://github.com/w3c/rdf-tests/pull/61). - SPARQL: fixes SPARQL-star evaluation of nested triples with both variables and constants. - SPARQL: if results are sorted, literals are now ordered by value, then datatype, then language tag. This ordering is considered as "implementation defined" by the SPARQL specification and is very likely to change in the future. - Python: all costly methods now release the python GIL allowing multithreaded usages of pyoxigraph. - Rust: SPARQL results writer now flushes the buffer at the end of the results writes. This makes their API less error-prone. - Rust: the bulk loader API has been rewritten to allow hooking a progress indicator and set parallelism limit. - Server: it is now possible to bulk load gzipped files. ## [0.3.0-beta.3] - 2022-02-02 ### Changed - Fixes a bug in the `bulk_load_dataset` method that was creating an invalid database. - Server: Takes into account also URL query parameters if the send SPARQL request body is using form-urlencoded. - Upgrades RocksDB to v0.28.2. - Generate clean python sdist files compiling Oxigraph from scratch with the proper `Cargo.lock`. - Do not push beta releases to homebrew and python stable documentation. - Moves RocksDB binding directory to `oxrocksdb-sys`. ## [0.3.0-beta.2] - 2022-01-29 ### Changed - Fixes release on crates.io of the RocksDB bindings. ## [0.3.0-beta.1] - 2022-01-29 ### Added - [RDF-star](https://w3c.github.io/rdf-star/cg-spec/2021-12-17.html) support. `Triple` is now a possible `Term`. Serialization formats and SPARQL support have been updated to match the [latest version of the specification draft](https://w3c.github.io/rdf-star/cg-spec/2021-12-17.html). - Fast data bulk load with the `Store` `bulk_load_dataset` and `bulk_load_graph` methods and a special command line option of the server. - It is now possible to quickly backup the database using the `backup` method. - Rust: `*Syntax::from_extension` to easy guess a graph/dataset/sparql result format from a file extension. - Rust: Custom SPARQL functions are now supported using `QueryOptions::with_custom_function`. - Rust: Simple in-memory graph (`Graph`) and dataset (`Dataset`) data structures with canonicalization. - Nightly build of the server binary and docker image, and of pyoxigraph wheels. - `Store` operations are now transactional using the "repeatable read" isolation level: the store only exposes changes that have been "committed" (i.e. no partial writes) and the exposed state does not change for the complete duration of a read operation (e.g. a SPARQL query) or a read/write operation (e.g. a SPARQL update). the `Store` `transaction` method now allows to do read/write transactions. -`RDF-star `_ is now supported (including serialization formats and SPARQL-star). :py:class:`.Triple` can now be used in :py:attr:`.Triple.object`, :py:attr:`.Triple.object`, :py:attr:`.Quad.subject` and :py:attr:`.Quad.object`. ### Changed - SPARQL: It is now possible to compare `rdf:langString` literals with the same language tag. - SPARQL: The parser now validates more carefully the inputs following the SPARQL specification and test suite. - SPARQL: Variable scoping was buggy with "FILTER EXISTS". It is now fixed. - Rust: RDF model, SPARQL parser and SPARQL result parsers have been moved to stand-alone reusable libraries. - Rust: HTTPS is not supported by default with the `http_client` option. You need to enable the `native-tls` or the `rustls` feature of the `oxhttp` crate to enable a TSL layer. - Rust: The error types have been cleaned. Most of the `Store` methods now return a `StorageError` that is more descriptive than the previous `std::io::Error`. The new error type all implements `Into` for easy conversion. - Rust: There is now a `Subject` struct that is the union of `NamedNode`, `BlankNode` and `Triple`. It is The used type of the `subject` field of the `Triple` and `Quad` structs. - Rust: The SPARQL algebra is not anymore publicly exposed in the `oxigraph` crate. The new `oxalgebra` crate exposes it. - Rust: `UpdateOptions` API have been rewritten. It can now be built using `From` or `Default`. - Server: The command line API has been redesign. See the [server README](server/README.md) for more information. - Server: The HTTP implementation is now provided by [`oxhttp`](https://github.com/oxigraph/oxhttp). - Server: The HTTP response bodies are now generated on the fly instead of being buffered. - Python: The `SledStore` and `MemoryStore` classes have been removed in favor of the `Store` class. - JS: The `MemoryStore` class has been renamed to `Store`. - JS: The [RDF/JS `DataFactory` interface](http://rdf.js.org/data-model-spec/#datafactory-interface) is now implemented by the `oxigraph` module itself and the `MemoryStore.dataFactory` property has been removed. - The implementation of SPARQL evaluation has been improved for better performances (especially joins). - The TLS implementation used in SPARQL HTTP calls is now [rustls](https://github.com/rustls/rustls) and not [native-tls](https://github.com/sfackler/rust-native-tls). The host system certificate registry is still used. - Spargebra: The basic RDF terms are now the ones of the `oxrdf` crate. ### Removed - `SledStore` and `MemoryStore`. There is only the `RocksDbStore` anymore that is renamed to `Store`. - `oxigraph_wikibase` is now stored in [its own repository](https://github.com/oxigraph/oxigraph-wikibase). - Rust: `From` implementations between `oxigraph` terms and `rio_api` terms. Many thanks to [Thad Guidry](https://github.com/thadguidry), [James Overton](https://github.com/jamesaoverton) and [Jeremiah](https://github.com/jeremiahpslewis) who sponsored the project during the development of this version. ## [0.2.5] - 2021-07-11 ### Added - [SPARQL 1.1 Query Results JSON Format](https://www.w3.org/TR/sparql11-results-json/) parser. - Python wheels for macOS are now universal2 binaries. ### Changed - The `Cargo.lock` file is now provided with releases to avoid compilation failures because of changes in dependencies. - Uses clap instead of argh for the server arguments parsing. - Upgrades PyO3 to v0.14. ## [0.2.4] - 2021-04-28 ### Changed - The HTTP server allows to query the union of all graphs using the `union-default-graph` query parameter and to use the union graph for update `WHERE` clauses using the `using-union-graph` parameter. - Exposes Sled flush operation (useful for platforms without auto-flush like Windows or Android). - Fixes a possible out of bound panic in SPARQL query evaluation. - Upgrades RocksDB to 6.17.3. ## [0.2.3] - 2021-04-11 ### Changed - Server: Fixes HTTP content negotiation (charset constraints, failure to properly handle `*/*`...). - Makes Clippy 1.51 happy. ## [0.2.2] - 2021-03-18 ### Added - Support of XML entities to the RDF/XML parser ### Changed - Serve: Allows unsupported query parameters in HTTP SPARQL requests. - Fixes WASM compilation bug and optimises WASM release packages. - Fixes named graph creation inside of a SledStore transaction. ## [0.2.1] - 2021-01-16 ### Changed - Fixes `pyoxigraph` build by enforcing a given `maturin` version. - Adds code to build Python wheels for MacOS and Windows. ## [0.2.0] - 2021-01-07 ### Added - [SPARQL 1.1 Update](https://www.w3.org/TR/sparql11-update/) support for Rust, Python and JavaScript. All store-like classes now provide an `update` method. - [SPARQL 1.1 Query Results CSV and TSV Formats](https://www.w3.org/TR/sparql11-results-csv-tsv/) serializers and TSV format parser. - [SPARQL 1.1 Graph Store HTTP Protocol](https://www.w3.org/TR/sparql11-http-rdf-update/) partial support in `oxigraph_server`. This protocol is accessible under the `/store` path. - The SPARQL Query and Update algebra is now public. - The stores are now "graph aware" i.e. it is possible to create and keep empty named graphs. - A simple built-in HTTP client. In the Rust library, is disabled by default behind the `http_client` feature. It powers SPARQL federation and SPARQL UPDATE `LOAD` operations. - `std::str::FromStr` implementations to `NamedNode`, `BlankNode`, `Literal`, `Term` and `Variable` allowing to easily parse Turtle/SPARQL serialization of these terms. - Optional Sled storage for `oxigraph_server`. ### Removed - The `default_graph_uris` and `named_graph_uris` parameters from `pyoxigraph` `query` methods. - Python 3.5 support. - `(Memory|RocksDB|Sled)Store::prepare_query` methods. It is possible to cache SPARQL query parsing using the `Query::parse` function and give the parsed query to the `query` method. ### Changed - Loading data into `oxigraph_server` is now possible using `/store` and not anymore using `/`. For example, you should use now `curl -f -X POST -H 'Content-Type:application/n-quads' --data-binary "@MY_FILE.nq" http://localhost:7878/store` to add the N-Quads file MY_FILE.nt to the server dataset. - Fixes evaluation of `MONTH()` and `DAY()` functions on the `xsd:date` values. - `Variable::new` now validates the variable name. - `(Memory|RocksDB|Sled)Store::query` does not have an option parameter anymore. There is now a new `query_opt` method that allows giving options. - `xsd:boolean` SPARQL function now properly follows XPath specification. - Fixes SPARQL `DESCRIBE` evaluation. ### Disk data format The disk data format has been changed between Oxigraph 0.1 (version 0) and Oxigraph 0.2 (version 1). Data is automatically migrated from the version 0 format to the version 1 format when opened with Oxigraph 0.2. ## [0.1.1] - 2020-08-14 ### Added - The `"sophia"` feature implementing the [`sophia_api`](https://docs.rs/sophia_api/) traits on Oxigraph terms and stores. - Explicit types for quads iterators returned by stores. ### Changed - `QueryOptions::with_default_graph` now takes an `impl Into` instead of an `impl Into`. - `QueryOptions::with_named_graph` now takes an `impl Into` instead of an `impl Into`. - `pyoxigraph` `query` methods now takes two new parameters, `default_graph` and `named_graphs`. `default_graph_uris` and `named_graph_uris` parameters are deprecated. - Fixes a bug in `xsd:gYear` parsing. ## [0.1.0] - 2020-08-09 ### Added - `QueryOptions` now allows settings the query dataset graph URIs (the SPARQL protocol `default-graph-uri` and `named-graph-uri` parameters). - `pyoxigraph` store `query` methods allows to provide the dataset graph URIs. It also provides an option to use all graph names as the default graph. - "default graph as union option" now works with FROM NAMED. - `pyoxigraph` now exposes and documents `Variable`, `QuerySolution`, `QuerySolutions` and `QueryTriples` ## [0.1.0-rc.1] - 2020-08-08 ### Added - `oxigraph` Rust library with SPARQL 1.1 query support and memory, Sled and RocksDB stores. - `oxigraph_server` standalone SPARQL server. - `oxigraph_wikibase` standalone SPARQL server loading data from a Wikibase instance. - `pyoxigraph` Python library based on Oxigraph. - `oxigraph` NodeJS library based on Oxigraph. oxigraph-0.3.22/CITATION.cff000066400000000000000000000007501453236674100153260ustar00rootroot00000000000000cff-version: 1.2.0 abstract: "Oxigraph is a graph database implementing the SPARQL standard." authors: - given-names: Thomas family-names: Pellissier Tanon email: thomas@pellissier-tanon.fr orcid: "https://orcid.org/0000-0002-0620-6486" doi: 10.5281/zenodo.7408022 license: - Apache-2.0 - MIT message: "If you use this software, please cite it as below." repository-code: "https://github.com/oxigraph/oxigraph" title: Oxigraph type: software url: "https://oxigraph.org" oxigraph-0.3.22/Cargo.lock000066400000000000000000001470751453236674100153550ustar00rootroot00000000000000# This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "adler" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6748e8def348ed4d14996fa801f4122cd763fff530258cdc03f64b25f89d3a5a" dependencies = [ "memchr", ] [[package]] name = "anes" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anyhow" version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "arbitrary" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2d098ff73c1ca148721f37baad5ea6a465a13f9573aba8641fbbbae8164a54e" dependencies = [ "derive_arbitrary", ] [[package]] name = "assert_cmd" version = "2.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9834fcc22e0874394a010230586367d4a3e9f11b560f469262678547e1d2575e" dependencies = [ "bstr", "doc-comment", "predicates", "predicates-core", "predicates-tree", "wait-timeout", ] [[package]] name = "assert_fs" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d94b2a3f3786ff2996a98afbd6b4e5b7e890d685ccf67577f508ee2342c71cc9" dependencies = [ "doc-comment", "globwalk", "predicates", "predicates-core", "predicates-tree", "tempfile", ] [[package]] name = "atty" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ "hermit-abi 0.1.19", "libc", "winapi 0.3.9", ] [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base64" version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" [[package]] name = "bindgen" version = "0.66.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2b84e06fc203107bfbad243f4aba2af864eb7db3b1cf46ea0a023b0b433d2a7" dependencies = [ "bitflags 2.4.0", "cexpr", "clang-sys", "lazy_static", "lazycell", "log", "peeking_take_while", "prettyplease", "proc-macro2", "quote", "regex", "rustc-hash", "shlex", "syn 2.0.29", "which", ] [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" [[package]] name = "block-buffer" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ "generic-array", ] [[package]] name = "bstr" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05" dependencies = [ "memchr", "regex-automata", "serde", ] [[package]] name = "bumpalo" version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" [[package]] name = "cast" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" dependencies = [ "jobserver", ] [[package]] name = "cexpr" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" dependencies = [ "nom", ] [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "ciborium" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926" dependencies = [ "ciborium-io", "ciborium-ll", "serde", ] [[package]] name = "ciborium-io" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656" [[package]] name = "ciborium-ll" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b" dependencies = [ "ciborium-io", "half", ] [[package]] name = "clang-sys" version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" dependencies = [ "glob", "libc", "libloading", ] [[package]] name = "clap" version = "3.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" dependencies = [ "bitflags 1.3.2", "clap_lex 0.2.4", "indexmap", "textwrap", ] [[package]] name = "clap" version = "4.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7db700bc935f9e43e88d00b0850dae18a63773cfbec6d8e070fccf7fef89a39" dependencies = [ "bitflags 1.3.2", "clap_derive", "clap_lex 0.3.0", "is-terminal", "once_cell", "strsim", "termcolor", ] [[package]] name = "clap_derive" version = "4.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014" dependencies = [ "heck", "proc-macro-error", "proc-macro2", "quote", "syn 1.0.109", ] [[package]] name = "clap_lex" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" dependencies = [ "os_str_bytes", ] [[package]] name = "clap_lex" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8" dependencies = [ "os_str_bytes", ] [[package]] name = "console_error_panic_hook" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" dependencies = [ "cfg-if", "wasm-bindgen", ] [[package]] name = "core-foundation" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" dependencies = [ "core-foundation-sys", "libc", ] [[package]] name = "core-foundation-sys" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" dependencies = [ "libc", ] [[package]] name = "crc32fast" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" dependencies = [ "cfg-if", ] [[package]] name = "criterion" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7c76e09c1aae2bc52b3d2f29e13c6572553b30c4aa1b8a49fd70de6412654cb" dependencies = [ "anes", "atty", "cast", "ciborium", "clap 3.2.25", "criterion-plot", "itertools", "lazy_static", "num-traits", "oorandom", "plotters", "rayon", "regex", "serde", "serde_derive", "serde_json", "tinytemplate", "walkdir", ] [[package]] name = "criterion-plot" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" dependencies = [ "cast", "itertools", ] [[package]] name = "crossbeam-channel" version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" dependencies = [ "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-deque" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" dependencies = [ "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" version = "0.9.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" dependencies = [ "autocfg", "cfg-if", "crossbeam-utils", "memoffset", "scopeguard", ] [[package]] name = "crossbeam-utils" version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" dependencies = [ "cfg-if", ] [[package]] name = "crypto-common" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", "typenum", ] [[package]] name = "deranged" version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946" [[package]] name = "derive_arbitrary" version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53e0efad4403bfc52dc201159c4b842a246a14b98c64b55dfd0f2d89729dfeb8" dependencies = [ "proc-macro2", "quote", "syn 2.0.29", ] [[package]] name = "difflib" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" [[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", ] [[package]] name = "doc-comment" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] name = "either" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "errno" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" dependencies = [ "errno-dragonfly", "libc", "windows-sys", ] [[package]] name = "errno-dragonfly" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" dependencies = [ "cc", "libc", ] [[package]] name = "escargot" version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f5584ba17d7ab26a8a7284f13e5bd196294dd2f2d79773cff29b9e9edef601a6" dependencies = [ "log", "once_cell", "serde", "serde_json", ] [[package]] name = "fastrand" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" dependencies = [ "instant", ] [[package]] name = "flate2" version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" dependencies = [ "crc32fast", "miniz_oxide", ] [[package]] name = "float-cmp" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" dependencies = [ "num-traits", ] [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" dependencies = [ "percent-encoding", ] [[package]] name = "generic-array" version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", ] [[package]] name = "getopts" version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" dependencies = [ "unicode-width", ] [[package]] name = "getrandom" version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "js-sys", "libc", "wasi", "wasm-bindgen", ] [[package]] name = "glob" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "globset" version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d" dependencies = [ "aho-corasick", "bstr", "fnv", "log", "regex", ] [[package]] name = "globwalk" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc" dependencies = [ "bitflags 1.3.2", "ignore", "walkdir", ] [[package]] name = "half" version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" [[package]] name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "heck" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" dependencies = [ "libc", ] [[package]] name = "hermit-abi" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" [[package]] name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "httparse" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "idna" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" dependencies = [ "unicode-bidi", "unicode-normalization", ] [[package]] name = "ignore" version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "713f1b139373f96a2e0ce3ac931cd01ee973c3c5dd7c40c0c2efe96ad2b6751d" dependencies = [ "crossbeam-utils", "globset", "lazy_static", "log", "memchr", "regex", "same-file", "thread_local", "walkdir", "winapi-util", ] [[package]] name = "indexmap" version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown", ] [[package]] name = "indoc" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306" [[package]] name = "instant" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ "cfg-if", ] [[package]] name = "io-lifetimes" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ "hermit-abi 0.3.2", "libc", "windows-sys", ] [[package]] name = "is-terminal" version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" dependencies = [ "hermit-abi 0.3.2", "io-lifetimes", "rustix", "windows-sys", ] [[package]] name = "itertools" version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" dependencies = [ "either", ] [[package]] name = "itoa" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "jobserver" version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" dependencies = [ "libc", ] [[package]] name = "js-sys" version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" dependencies = [ "wasm-bindgen", ] [[package]] name = "json-event-parser" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32f12e624eaeb74accb9bb48f01cb071427f68115aaafa5689acb372d7e22977" [[package]] name = "kernel32-sys" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" dependencies = [ "winapi 0.2.8", "winapi-build", ] [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "lazycell" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "libloading" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" dependencies = [ "cfg-if", "winapi 0.3.9", ] [[package]] name = "linux-raw-sys" version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "lock_api" version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" dependencies = [ "autocfg", "scopeguard", ] [[package]] name = "log" version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "md-5" version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca" dependencies = [ "digest", ] [[package]] name = "memchr" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memoffset" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" dependencies = [ "autocfg", ] [[package]] name = "minimal-lexical" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" dependencies = [ "adler", ] [[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 = "normalize-line-endings" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" [[package]] name = "num-traits" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" dependencies = [ "autocfg", ] [[package]] name = "num_cpus" version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ "hermit-abi 0.3.2", "libc", ] [[package]] name = "once_cell" version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "oorandom" version = "11.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" [[package]] name = "openssl-probe" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "os_str_bytes" version = "6.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac" [[package]] name = "oxhttp" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64f8f4b616372a7e657a05100d1389325fc2f7d3fee5c9de05166d979cb2b729" dependencies = [ "httparse", "lazy_static", "rayon-core", "rustls", "rustls-native-certs", "url", ] [[package]] name = "oxigraph" version = "0.3.22" dependencies = [ "criterion", "digest", "getrandom", "hex", "js-sys", "json-event-parser", "lazy_static", "libc", "md-5", "oxhttp", "oxilangtag", "oxiri", "oxrdf", "oxrocksdb-sys", "oxsdatatypes", "rand", "regex", "rio_api", "rio_turtle", "rio_xml", "sha-1", "sha2", "siphasher", "sparesults", "spargebra", "zstd", ] [[package]] name = "oxigraph_js" version = "0.3.22" dependencies = [ "console_error_panic_hook", "js-sys", "oxigraph", "wasm-bindgen", ] [[package]] name = "oxigraph_server" version = "0.3.22" dependencies = [ "anyhow", "assert_cmd", "assert_fs", "clap 4.0.32", "clap_lex 0.3.0", "escargot", "flate2", "ignore", "is-terminal", "oxhttp", "oxigraph", "oxiri", "predicates", "predicates-core", "predicates-tree", "rand", "rayon-core", "sparesults", "tempfile", "url", ] [[package]] name = "oxigraph_testsuite" version = "0.0.0" dependencies = [ "anyhow", "clap 4.0.32", "criterion", "oxigraph", "text-diff", "time", ] [[package]] name = "oxilangtag" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d91edf4fbb970279443471345a4e8c491bf05bb283b3e6c88e4e606fd8c181b" [[package]] name = "oxiri" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb175ec8981211357b7b379869c2f8d555881c55ea62311428ec0de46d89bd5c" [[package]] name = "oxrdf" version = "0.1.7" dependencies = [ "oxilangtag", "oxiri", "oxsdatatypes", "rand", ] [[package]] name = "oxrocksdb-sys" version = "0.3.22" dependencies = [ "bindgen", "cc", "libc", ] [[package]] name = "oxsdatatypes" version = "0.1.3" dependencies = [ "js-sys", ] [[package]] name = "parking_lot" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", "parking_lot_core", ] [[package]] name = "parking_lot_core" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", "windows-targets", ] [[package]] name = "peeking_take_while" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" [[package]] name = "peg" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a07f2cafdc3babeebc087e499118343442b742cc7c31b4d054682cc598508554" dependencies = [ "peg-macros", "peg-runtime", ] [[package]] name = "peg-macros" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a90084dc05cf0428428e3d12399f39faad19b0909f64fb9170c9fdd6d9cd49b" dependencies = [ "peg-runtime", "proc-macro2", "quote", ] [[package]] name = "peg-runtime" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa00462b37ead6d11a82c9d568b26682d78e0477dc02d1966c013af80969739" [[package]] name = "percent-encoding" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pkg-config" version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" [[package]] name = "plotters" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" dependencies = [ "num-traits", "plotters-backend", "plotters-svg", "wasm-bindgen", "web-sys", ] [[package]] name = "plotters-backend" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" [[package]] name = "plotters-svg" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" dependencies = [ "plotters-backend", ] [[package]] name = "ppv-lite86" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "predicates" version = "2.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59230a63c37f3e18569bdb90e4a89cbf5bf8b06fea0b84e65ea10cc4df47addd" dependencies = [ "difflib", "float-cmp", "itertools", "normalize-line-endings", "predicates-core", "regex", ] [[package]] name = "predicates-core" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72f883590242d3c6fc5bf50299011695fa6590c2c70eac95ee1bdb9a733ad1a2" [[package]] name = "predicates-tree" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54ff541861505aabf6ea722d2131ee980b8276e10a1297b94e896dd8b621850d" dependencies = [ "predicates-core", "termtree", ] [[package]] name = "prettyplease" version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c64d9ba0963cdcea2e1b2230fbae2bab30eb25a174be395c41e764bfb65dd62" dependencies = [ "proc-macro2", "syn 2.0.29", ] [[package]] name = "proc-macro-error" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote", "syn 1.0.109", "version_check", ] [[package]] name = "proc-macro-error-attr" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ "proc-macro2", "quote", "version_check", ] [[package]] name = "proc-macro2" version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" dependencies = [ "unicode-ident", ] [[package]] name = "pyo3" version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e681a6cfdc4adcc93b4d3cf993749a4552018ee0a9b65fc0ccfad74352c72a38" dependencies = [ "cfg-if", "indoc", "libc", "memoffset", "parking_lot", "pyo3-build-config", "pyo3-ffi", "pyo3-macros", "unindent", ] [[package]] name = "pyo3-build-config" version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "076c73d0bc438f7a4ef6fdd0c3bb4732149136abd952b110ac93e4edb13a6ba5" dependencies = [ "once_cell", "target-lexicon", ] [[package]] name = "pyo3-ffi" version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e53cee42e77ebe256066ba8aa77eff722b3bb91f3419177cf4cd0f304d3284d9" dependencies = [ "libc", "pyo3-build-config", ] [[package]] name = "pyo3-macros" version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfeb4c99597e136528c6dd7d5e3de5434d1ceaf487436a3f03b2d56b6fc9efd1" dependencies = [ "proc-macro2", "pyo3-macros-backend", "quote", "syn 1.0.109", ] [[package]] name = "pyo3-macros-backend" version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "947dc12175c254889edc0c02e399476c2f652b4b9ebd123aa655c224de259536" dependencies = [ "proc-macro2", "quote", "syn 1.0.109", ] [[package]] name = "pyoxigraph" version = "0.3.22" dependencies = [ "oxigraph", "pyo3", ] [[package]] name = "quick-xml" version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce5e73202a820a31f8a0ee32ada5e21029c81fd9e3ebf668a40832e4219d9d1" dependencies = [ "memchr", ] [[package]] name = "quote" version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" 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.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" dependencies = [ "either", "rayon-core", ] [[package]] name = "rayon-core" version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" dependencies = [ "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", "num_cpus", ] [[package]] name = "redox_syscall" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "regex" version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" dependencies = [ "aho-corasick", "memchr", "regex-automata", "regex-syntax", ] [[package]] name = "regex-automata" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" [[package]] name = "ring" version = "0.16.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" dependencies = [ "cc", "libc", "once_cell", "spin", "untrusted", "web-sys", "winapi 0.3.9", ] [[package]] name = "rio_api" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1924fa1f0e6d851f9b73b3c569e607c368a0d92995d99d563ad7bf1414696603" [[package]] name = "rio_turtle" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5cec59971eafd99b9c7e3544bfcabafea81a7072ac51c9f46985ca0bd7ba6016" dependencies = [ "oxilangtag", "oxiri", "rio_api", ] [[package]] name = "rio_xml" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2edda57b877119dc326c612ba822e3ca1ee22bfc86781a4e9dc0884756b58c3" dependencies = [ "oxilangtag", "oxiri", "quick-xml", "rio_api", ] [[package]] name = "rustc-hash" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustix" version = "0.37.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4eb579851244c2c03e7c24f501c3432bed80b8f720af1d6e5b0e0f01555a035" dependencies = [ "bitflags 1.3.2", "errno", "io-lifetimes", "libc", "linux-raw-sys", "windows-sys", ] [[package]] name = "rustls" version = "0.21.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d1feddffcfcc0b33f5c6ce9a29e341e4cd59c3f78e7ee45f4a40c038b1d6cbb" dependencies = [ "log", "ring", "rustls-webpki", "sct", ] [[package]] name = "rustls-native-certs" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" dependencies = [ "openssl-probe", "rustls-pemfile", "schannel", "security-framework", ] [[package]] name = "rustls-pemfile" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" dependencies = [ "base64", ] [[package]] name = "rustls-webpki" version = "0.101.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d93931baf2d282fff8d3a532bbfd7653f734643161b87e3e01e59a04439bf0d" dependencies = [ "ring", "untrusted", ] [[package]] name = "ryu" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "same-file" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" dependencies = [ "winapi-util", ] [[package]] name = "schannel" version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" dependencies = [ "windows-sys", ] [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sct" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" dependencies = [ "ring", "untrusted", ] [[package]] name = "security-framework" version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" dependencies = [ "bitflags 1.3.2", "core-foundation", "core-foundation-sys", "libc", "security-framework-sys", ] [[package]] name = "security-framework-sys" version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" dependencies = [ "core-foundation-sys", "libc", ] [[package]] name = "serde" version = "1.0.185" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be9b6f69f1dfd54c3b568ffa45c310d6973a5e5148fd40cf515acaf38cf5bc31" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.185" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc59dfdcbad1437773485e0367fea4b090a2e0a16d9ffc46af47764536a298ec" dependencies = [ "proc-macro2", "quote", "syn 2.0.29", ] [[package]] name = "serde_json" version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360" dependencies = [ "itoa", "ryu", "serde", ] [[package]] name = "sha-1" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" dependencies = [ "cfg-if", "cpufeatures", "digest", ] [[package]] name = "sha2" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" dependencies = [ "cfg-if", "cpufeatures", "digest", ] [[package]] name = "shlex" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" [[package]] name = "siphasher" version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] name = "smallvec" version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" [[package]] name = "sparesults" version = "0.1.8" dependencies = [ "json-event-parser", "oxrdf", "quick-xml", ] [[package]] name = "spargebra" version = "0.2.8" dependencies = [ "oxilangtag", "oxiri", "oxrdf", "peg", "rand", ] [[package]] name = "sparql-smith" version = "0.1.0-alpha.4" dependencies = [ "arbitrary", ] [[package]] name = "spin" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "strsim" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "syn" version = "2.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "target-lexicon" version = "0.12.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d0e916b1148c8e263850e1ebcbd046f333e0683c724876bb0da63ea4373dc8a" [[package]] name = "tempfile" version = "3.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" dependencies = [ "autocfg", "cfg-if", "fastrand", "redox_syscall", "rustix", "windows-sys", ] [[package]] name = "term" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2077e54d38055cf1ca0fd7933a2e00cd3ec8f6fed352b2a377f06dcdaaf3281" dependencies = [ "kernel32-sys", "winapi 0.2.8", ] [[package]] name = "termcolor" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" dependencies = [ "winapi-util", ] [[package]] name = "termtree" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" [[package]] name = "text-diff" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "309238dd66f8bf11a20d015b727b926f294a13fcb8d56770bb984e7a22c43897" dependencies = [ "getopts", "term", ] [[package]] name = "textwrap" version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thread_local" version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" dependencies = [ "cfg-if", "once_cell", ] [[package]] name = "time" version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bb39ee79a6d8de55f48f2293a830e040392f1c5f16e336bdd1788cd0aadce07" dependencies = [ "deranged", "itoa", "serde", "time-core", "time-macros", ] [[package]] name = "time-core" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" [[package]] name = "time-macros" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "733d258752e9303d392b94b75230d07b0b9c489350c69b851fc6c065fde3e8f9" dependencies = [ "time-core", ] [[package]] name = "tinytemplate" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" dependencies = [ "serde", "serde_json", ] [[package]] name = "tinyvec" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" dependencies = [ "tinyvec_macros", ] [[package]] name = "tinyvec_macros" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "typenum" version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "unicode-bidi" version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" [[package]] name = "unicode-normalization" version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" dependencies = [ "tinyvec", ] [[package]] name = "unicode-width" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "unindent" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1766d682d402817b5ac4490b3c3002d91dfa0d22812f341609f97b08757359c" [[package]] name = "untrusted" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "url" version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" dependencies = [ "form_urlencoded", "idna", "percent-encoding", ] [[package]] name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wait-timeout" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" dependencies = [ "libc", ] [[package]] name = "walkdir" version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" dependencies = [ "same-file", "winapi-util", ] [[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.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" dependencies = [ "cfg-if", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", "syn 2.0.29", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" dependencies = [ "quote", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", "syn 2.0.29", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "web-sys" version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" dependencies = [ "js-sys", "wasm-bindgen", ] [[package]] name = "which" version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" dependencies = [ "either", "libc", "once_cell", ] [[package]] name = "winapi" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" [[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-build" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" [[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.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ "winapi 0.3.9", ] [[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-sys" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "zstd" version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a27595e173641171fc74a1232b7b1c7a7cb6e18222c11e9dfb9888fa424c53c" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" version = "6.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee98ffd0b48ee95e6c5168188e44a54550b1564d9d530ee21d5f0eaed1069581" dependencies = [ "libc", "zstd-sys", ] [[package]] name = "zstd-sys" version = "2.0.8+zstd.1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5556e6ee25d32df2586c098bbfa278803692a20d0ab9565e049480d52707ec8c" dependencies = [ "cc", "libc", "pkg-config", ] oxigraph-0.3.22/Cargo.toml000066400000000000000000000005221453236674100153610ustar00rootroot00000000000000[workspace] members = [ "js", "lib", "lib/oxrdf", "lib/oxsdatatypes", "lib/spargebra", "lib/sparesults", "lib/sparql-smith", "oxrocksdb-sys", "python", "server", "testsuite" ] resolver = "2" [profile.release] lto = true codegen-units = 1 [profile.release.package.oxigraph_js] opt-level = "z" oxigraph-0.3.22/LICENSE-APACHE000066400000000000000000000251371453236674100153660ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. oxigraph-0.3.22/LICENSE-MIT000066400000000000000000000020471453236674100150710ustar00rootroot00000000000000Copyright (c) 2018 Oxigraph developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. oxigraph-0.3.22/README.md000066400000000000000000000140261453236674100147140ustar00rootroot00000000000000# Oxigraph [![Latest Version](https://img.shields.io/crates/v/oxigraph.svg)](https://crates.io/crates/oxigraph) [![Released API docs](https://docs.rs/oxigraph/badge.svg)](https://docs.rs/oxigraph) [![PyPI](https://img.shields.io/pypi/v/pyoxigraph)](https://pypi.org/project/pyoxigraph/) [![npm](https://img.shields.io/npm/v/oxigraph)](https://www.npmjs.com/package/oxigraph) [![actions status](https://github.com/oxigraph/oxigraph/workflows/build/badge.svg)](https://github.com/oxigraph/oxigraph/actions) [![dependency status](https://deps.rs/repo/github/oxigraph/oxigraph/status.svg)](https://deps.rs/repo/github/oxigraph/oxigraph) [![Gitter](https://badges.gitter.im/oxigraph/community.svg)](https://gitter.im/oxigraph/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![Twitter URL](https://img.shields.io/twitter/url?style=social&url=https%3A%2F%2Ftwitter.com%2Foxigraph)](https://twitter.com/oxigraph) Oxigraph is a graph database implementing the [SPARQL](https://www.w3.org/TR/sparql11-overview/) standard. Its goal is to provide a compliant, safe, and fast graph database based on the [RocksDB](https://rocksdb.org/) key-value store. It is written in Rust. It also provides a set of utility functions for reading, writing, and processing RDF files. Oxigraph is in heavy development and SPARQL query evaluation has not been optimized yet. The development roadmap is using [GitHub milestones](https://github.com/oxigraph/oxigraph/milestones?direction=desc&sort=completeness&state=open). Oxigraph internal design [is described on the wiki](https://github.com/oxigraph/oxigraph/wiki/Architecture). The future 0.4 release is currently in development in the [next branch](https://github.com/oxigraph/oxigraph/tree/next). It is split into multiple parts: - [The database written as a Rust library](https://crates.io/crates/oxigraph). Its source code is in the `lib` directory. [![Latest Version](https://img.shields.io/crates/v/oxigraph.svg)](https://crates.io/crates/oxigraph) [![Released API docs](https://docs.rs/oxigraph/badge.svg)](https://docs.rs/oxigraph) - [`pyoxigraph` that exposes Oxigraph to the Python world](https://pyoxigraph.readthedocs.io/). Its source code is in the `python` directory. [![PyPI](https://img.shields.io/pypi/v/pyoxigraph)](https://pypi.org/project/pyoxigraph/) - [JavaScript bindings for Oxigraph](https://www.npmjs.com/package/oxigraph). WebAssembly is used to package Oxigraph into a NodeJS compatible NPM package. Its source code is in the `js` directory. [![npm](https://img.shields.io/npm/v/oxigraph)](https://www.npmjs.com/package/oxigraph) - [Oxigraph server](https://crates.io/crates/oxigraph_server) that provides a standalone binary of a web server implementing the [SPARQL 1.1 Protocol](https://www.w3.org/TR/sparql11-protocol/) and the [SPARQL 1.1 Graph Store Protocol](https://www.w3.org/TR/sparql11-http-rdf-update/). Its source code is in the `server` directory. [![Latest Version](https://img.shields.io/crates/v/oxigraph_server.svg)](https://crates.io/crates/oxigraph_server) Oxigraph implements the following specifications: - [SPARQL 1.1 Query](https://www.w3.org/TR/sparql11-query/), [SPARQL 1.1 Update](https://www.w3.org/TR/sparql11-update/), and [SPARQL 1.1 Federated Query](https://www.w3.org/TR/sparql11-federated-query/). - [Turtle](https://www.w3.org/TR/turtle/), [TriG](https://www.w3.org/TR/trig/), [N-Triples](https://www.w3.org/TR/n-triples/), [N-Quads](https://www.w3.org/TR/n-quads/), and [RDF XML](https://www.w3.org/TR/rdf-syntax-grammar/) RDF serialization formats for both data ingestion and retrieval using the [Rio library](https://github.com/oxigraph/rio). - [SPARQL Query Results XML Format](https://www.w3.org/TR/rdf-sparql-XMLres/), [SPARQL 1.1 Query Results JSON Format](https://www.w3.org/TR/sparql11-results-json/) and [SPARQL 1.1 Query Results CSV and TSV Formats](https://www.w3.org/TR/sparql11-results-csv-tsv/). A preliminary benchmark [is provided](bench/README.md). There is also [a document describing Oxigraph technical architecture](https://github.com/oxigraph/oxigraph/wiki/Architecture). When cloning this codebase, don't forget to clone the submodules using `git clone --recursive https://github.com/oxigraph/oxigraph.git` to clone the repository including submodules or `git submodule update --init` to add the submodules to the already cloned repository. ## Help Feel free to use [GitHub discussions](https://github.com/oxigraph/oxigraph/discussions) or [the Gitter chat](https://gitter.im/oxigraph/community) to ask questions or talk about Oxigraph. [Bug reports](https://github.com/oxigraph/oxigraph/issues) are also very welcome. If you need advanced support or are willing to pay to get some extra features, feel free to reach out to [Tpt](https://github.com/Tpt/). ## License This project is licensed under either of - Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) - MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) at your option. ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in Oxigraph by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. ## Sponsors * [RelationLabs](https://relationlabs.ai/) that is building [Relation-Graph](https://github.com/relationlabs/Relation-Graph), a SPARQL database module for the [Substrate blockchain platform](https://substrate.io/) based on Oxigraph. * [Field 33](https://field33.com) that is building [an ontology management platform](https://plow.pm/). * [Magnus Bakken](https://github.com/magbak) who is building [chrontext](https://github.com/magbak/chrontext), providing a SPARQL query endpoint on top of joint RDF and time series databases. * [ACE IoT Solutions](https://aceiotsolutions.com/), a building IOT platform. * [Albin Larsson](https://byabbe.se/) who is building [GovDirectory](https://www.govdirectory.org/), a directory of public agencies based on Wikidata. And [others](https://github.com/sponsors/Tpt). Many thanks to them! oxigraph-0.3.22/bench/000077500000000000000000000000001453236674100145115ustar00rootroot00000000000000oxigraph-0.3.22/bench/README.md000066400000000000000000000057731453236674100160040ustar00rootroot00000000000000BSBM ==== The [Berlin SPARQL Benchmark (BSBM)](http://wifo5-03.informatik.uni-mannheim.de/bizer/berlinsparqlbenchmark/) is a simple SPARQL benchmark. It provides a dataset generator and multiple sets of queries grouped by "use cases". ## Results We compare here Oxigraph 0.2 and 0.3 with some existing SPARQL implementations (Blazegraph, GraphDB, Jena, and Virtuoso). The dataset used in the following charts is generated with 100k "products" (see [its spec](http://wifo5-03.informatik.uni-mannheim.de/bizer/berlinsparqlbenchmark/spec/Dataset/index.html)). It leads to the creation of 35M triples. It has been executed on a PrevailPro P3000 with 32GB of RAM. The tests have been executed with a concurrency factor of 16 (i.e. at most 16 queries are sent at the same time to the server). Beware, the graph *y* axis is in log scale to properly display on the same graph systems with very different speed behaviors. ### Explore The [explore use case](http://wifo5-03.informatik.uni-mannheim.de/bizer/berlinsparqlbenchmark/spec/ExploreUseCase/index.html) is composed of 11 queries that do simple data retrieval. Query 6 existed in previous versions of the benchmark but is now removed. ![explore use case results](bsbm.explore.svg) ### Explore and update The [explore and update use case](http://wifo5-03.informatik.uni-mannheim.de/bizer/berlinsparqlbenchmark/spec/index.html#usecase_explore_and_update) is composed of the 2 operations of the [update use case](http://wifo5-03.informatik.uni-mannheim.de/bizer/berlinsparqlbenchmark/spec/UpdateUseCase/index.html) (`INSERT DATA` and `DELETE WHERE`) and the 11 queries of the [explore use case](http://wifo5-03.informatik.uni-mannheim.de/bizer/berlinsparqlbenchmark/spec/ExploreUseCase/index.html). The first two elements (1 and 2) are the 2 updates and the others (3 to 14) are the 11 queries. ![explore use case results](bsbm.exploreAndUpdate.svg) ## How to reproduce the benchmark The code of the benchmark is in the `bsbm-tools` submodule. You should pull it with a `git submodule update` before running the benchmark. To run the benchmark for Oxigraph run `bash bsbm_oxigraph.sh`. It will compile the current Oxigraph code and run the benchmark against it. You can tweak the number of products in the dataset and the number of concurrent requests using the environment variables at the beginning of `bsbm_oxigraph.sh`. To generate the plots run `python3 bsbsm-plot.py`. Scripts are also provided for the other systems (`bsbm_blazegraph.sh`, `bsbm_graphdb.sh`, `bsbm_jena.sh` and `bsbm_virtuoso.sh`). oxigraph-0.3.22/bench/bsbm-plot.py000066400000000000000000000037251453236674100167710ustar00rootroot00000000000000import matplotlib.pyplot as plt import xml.etree.ElementTree as ET from collections import defaultdict from glob import glob from numpy import array def plot_y_per_x_per_plot(data, xlabel, ylabel, file, log=False): plt.figure(file) bar_width = 1 / (len(data) + 1) for i, (label, xys) in enumerate(sorted(data.items())): plt.bar(array(list(xys.keys())) + bar_width * (i + 1 - len(data) / 2), array(list(xys.values())), bar_width, label=label) plt.legend() plt.xlabel(xlabel) plt.ylabel(ylabel) plt.yscale('log') if log: plt.yscale('log') plt.savefig(file) def plot_usecase(name: str): aqet = defaultdict(dict) avgresults_by_query = defaultdict(lambda: defaultdict(dict)) for file in glob('bsbm.{}.*.xml'.format(name)): parts = file.split('.') run = '.'.join(parts[2:-1]) for query in ET.parse(file).getroot().find('queries').findall('query'): query_id = int(query.attrib['nr']) for child in query.iter(): if child.tag == "aqet": val = float(query.find('aqet').text) if val > 0: aqet[run][query_id] = val elif child.tag == "avgresults": avgresults_by_query[query_id][int(parts[-3])][run] = float(query.find('avgresults').text) plot_y_per_x_per_plot(aqet, 'query id', 'execution time (s)', 'bsbm.{}.svg'.format(name)) # we check if avgresults seems consistent for query, t in avgresults_by_query.items(): for size, value_by_run in t.items(): avg = sum(value_by_run.values()) / len(value_by_run) if not all(abs(v - avg) < 1 for v in value_by_run.values()): print( f'Strange value for average results for usecase {name} of size {size} and query {query}: {value_by_run}') plot_usecase('explore') plot_usecase('exploreAndUpdate') plot_usecase('businessIntelligence') plt.show() oxigraph-0.3.22/bench/bsbm-tools/000077500000000000000000000000001453236674100165725ustar00rootroot00000000000000oxigraph-0.3.22/bench/bsbm.explore.svg000066400000000000000000001573451453236674100176510ustar00rootroot00000000000000 2022-01-29T14:06:50.368417 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/ oxigraph-0.3.22/bench/bsbm.exploreAndUpdate.svg000066400000000000000000001541131453236674100214250ustar00rootroot00000000000000 2022-01-29T14:06:51.041065 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/ oxigraph-0.3.22/bench/bsbm_blazegraph.sh000077500000000000000000000024141453236674100201730ustar00rootroot00000000000000#!/usr/bin/env bash DATASET_SIZE=100000 PARALLELISM=16 set -eu wget -nc https://github.com/blazegraph/database/releases/download/BLAZEGRAPH_RELEASE_2_1_5/blazegraph.jar cd bsbm-tools || exit ./generate -fc -pc ${DATASET_SIZE} -s nt -fn "explore-${DATASET_SIZE}" -ud -ufn "explore-update-${DATASET_SIZE}" /usr/lib/jvm/java-8-openjdk/bin/java -server -jar ../blazegraph.jar & sleep 10 curl -f -X POST -H 'Content-Type:text/turtle' -T "explore-${DATASET_SIZE}.nt" http://localhost:9999/blazegraph/sparql ./testdriver -mt ${PARALLELISM} -ucf usecases/explore/sparql.txt -o "../bsbm.explore.blazegraph.2.1.5.${DATASET_SIZE}.${PARALLELISM}.xml" http://localhost:9999/blazegraph/sparql ./testdriver -mt ${PARALLELISM} -ucf usecases/exploreAndUpdate/sparql.txt -o "../bsbm.exploreAndUpdate.blazegraph.2.1.5.${DATASET_SIZE}.${PARALLELISM}.xml" http://localhost:9999/blazegraph/sparql -u http://localhost:9999/blazegraph/sparql -udataset "explore-update-${DATASET_SIZE}.nt" #./testdriver -mt ${PARALLELISM} -ucf usecases/businessIntelligence/sparql.txt -o "../bsbm.businessIntelligence.blazegraph.2.1.5.${DATASET_SIZE}.${PARALLELISM}.xml" http://localhost:9999/blazegraph/sparql kill $! rm -f blazegraph.jnl rm -f "explore-${DATASET_SIZE}.nt" rm -f "explore-update-${DATASET_SIZE}.nt" rm -rf td_data oxigraph-0.3.22/bench/bsbm_graphdb.sh000077500000000000000000000040371453236674100174660ustar00rootroot00000000000000#!/usr/bin/env bash DATASET_SIZE=100000 PARALLELISM=16 VERSION="9.3.3" set -eu cd bsbm-tools ./generate -fc -pc ${DATASET_SIZE} -s nt -fn "explore-${DATASET_SIZE}" -ud -ufn "explore-update-${DATASET_SIZE}" ../graphdb-free-9.3.3/bin/graphdb -s -Dgraphdb.logger.root.level=WARN & sleep 10 curl -f -X POST http://localhost:7200/rest/repositories -H 'Content-Type:application/json' -d ' {"id":"bsbm","params":{"ruleset":{"label":"Ruleset","name":"ruleset","value":"empty"},"title":{"label":"Repository title","name":"title","value":"GraphDB Free repository"},"checkForInconsistencies":{"label":"Check for inconsistencies","name":"checkForInconsistencies","value":"false"},"disableSameAs":{"label":"Disable owl:sameAs","name":"disableSameAs","value":"true"},"baseURL":{"label":"Base URL","name":"baseURL","value":"http://example.org/owlim#"},"repositoryType":{"label":"Repository type","name":"repositoryType","value":"file-repository"},"id":{"label":"Repository ID","name":"id","value":"repo-bsbm"},"storageFolder":{"label":"Storage folder","name":"storageFolder","value":"storage"}},"title":"BSBM","type":"free"} ' curl -f -X PUT -H 'Content-Type:application/n-triples' -T "explore-${DATASET_SIZE}.nt" http://localhost:7200/repositories/bsbm/statements ./testdriver -mt ${PARALLELISM} -ucf usecases/explore/sparql.txt -o "../bsbm.explore.graphdb.${VERSION}.${DATASET_SIZE}.${PARALLELISM}.xml" http://localhost:7200/repositories/bsbm ./testdriver -mt ${PARALLELISM} -ucf usecases/exploreAndUpdate/sparql.txt -o "../bsbm.exploreAndUpdate.graphdb.${VERSION}.${DATASET_SIZE}.${PARALLELISM}.xml" http://localhost:7200/repositories/bsbm -u http://localhost:7200/repositories/bsbm/statements -udataset "explore-update-${DATASET_SIZE}.nt" #./testdriver -mt ${PARALLELISM} -ucf usecases/businessIntelligence/sparql.txt -o "../bsbm.businessIntelligence.graphdb.${VERSION}.${DATASET_SIZE}.${PARALLELISM}.xml" http://localhost:7200/repositories/bsbm kill $! sleep 5 rm -rf ../graphdb-free-9.3.3/data rm -f "explore-${DATASET_SIZE}.nt" rm -f "explore-update-${DATASET_SIZE}.nt" rm -rf td_data oxigraph-0.3.22/bench/bsbm_jena.sh000077500000000000000000000032151453236674100167710ustar00rootroot00000000000000#!/usr/bin/env bash DATASET_SIZE=100000 # number of products in the dataset. There is around 350 triples generated by product. PARALLELISM=16 VERSION="4.3.2" set -eu wget -nc https://downloads.apache.org/jena/binaries/apache-jena-${VERSION}.zip cd bsbm-tools || exit ./generate -fc -pc ${DATASET_SIZE} -s nt -fn "explore-${DATASET_SIZE}" -ud -ufn "explore-update-${DATASET_SIZE}" unzip ../"apache-jena-${VERSION}.zip" ./apache-jena-${VERSION}/bin/tdb2.tdbloader --loader=parallel --loc=td_data "explore-${DATASET_SIZE}.nt" wget https://downloads.apache.org/jena/binaries/apache-jena-fuseki-${VERSION}.zip unzip apache-jena-fuseki-${VERSION}.zip rm apache-jena-fuseki-${VERSION}.zip echo "rootLogger.level = ERROR" > ./apache-jena-fuseki-${VERSION}/log4j2.properties ./apache-jena-fuseki-${VERSION}/fuseki-server --tdb2 --loc=td_data --update /bsbm & sleep 10 ./testdriver -mt ${PARALLELISM} -ucf usecases/explore/sparql.txt -o "../bsbm.explore.jena.${VERSION}.${DATASET_SIZE}.${PARALLELISM}.xml" http://localhost:3030/bsbm/query ./testdriver -mt ${PARALLELISM} -ucf usecases/exploreAndUpdate/sparql.txt -o "../bsbm.exploreAndUpdate.jena.${VERSION}.${DATASET_SIZE}.${PARALLELISM}.xml" http://localhost:3030/bsbm/query -u http://localhost:3030/bsbm/update -udataset "explore-update-${DATASET_SIZE}.nt" #./testdriver -mt ${PARALLELISM} -ucf usecases/businessIntelligence/sparql.txt -o "../bsbm.businessIntelligence.jena.${VERSION}.${DATASET_SIZE}.${PARALLELISM}.xml" http://localhost:3030/bsbm/query kill $! rm -f "explore-${DATASET_SIZE}.nt" rm -f "explore-update-${DATASET_SIZE}.nt" rm -rf td_data rm -rf run rm -rf apache-jena-${VERSION} rm -rf apache-jena-fuseki-${VERSION} oxigraph-0.3.22/bench/bsbm_oxigraph.sh000077500000000000000000000025501453236674100176760ustar00rootroot00000000000000#!/usr/bin/env bash DATASET_SIZE=100000 # number of products in the dataset. There is around 350 triples generated by product. PARALLELISM=16 set -eu cd bsbm-tools ./generate -fc -pc ${DATASET_SIZE} -s nt -fn "explore-${DATASET_SIZE}" -ud -ufn "explore-update-${DATASET_SIZE}" cargo build --release --manifest-path="../../server/Cargo.toml" VERSION=$(./../../target/release/oxigraph_server --version | sed 's/oxigraph_server //g') ./../../target/release/oxigraph_server --location oxigraph_data load --file "explore-${DATASET_SIZE}.nt" ./../../target/release/oxigraph_server --location oxigraph_data serve --bind 127.0.0.1:7878 & sleep 1 ./testdriver -mt ${PARALLELISM} -ucf usecases/explore/sparql.txt -o "../bsbm.explore.oxigraph.${VERSION}.${DATASET_SIZE}.${PARALLELISM}.xml" http://127.0.0.1:7878/query ./testdriver -mt ${PARALLELISM} -ucf usecases/exploreAndUpdate/sparql.txt -o "../bsbm.exploreAndUpdate.oxigraph.${VERSION}.${DATASET_SIZE}.${PARALLELISM}.xml" http://127.0.0.1:7878/query -u http://127.0.0.1:7878/update -udataset "explore-update-${DATASET_SIZE}.nt" #./testdriver -mt ${PARALLELISM} -ucf usecases/businessIntelligence/sparql.txt -o "../bsbm.businessIntelligence.${VERSION}.${DATASET_SIZE}.${PARALLELISM}.xml" "http://127.0.0.1:7878/query" kill $! rm -rf oxigraph_data rm -f "explore-${DATASET_SIZE}.nt" rm -f "explore-update-${DATASET_SIZE}.nt" rm -rf td_data oxigraph-0.3.22/bench/bsbm_rdf4j.sh000077500000000000000000000052231453236674100170660ustar00rootroot00000000000000#!/usr/bin/env bash DATASET_SIZE=100000 PARALLELISM=16 VERSION="4.2.2" TOMCAT_VERSION="9.0.71" set -eu wget -nc -O "rdf4j-${VERSION}.zip" "https://www.eclipse.org/downloads/download.php?file=/rdf4j/eclipse-rdf4j-${VERSION}-sdk.zip&mirror_id=1" wget -nc -O "tomcat-${TOMCAT_VERSION}.zip" "https://dlcdn.apache.org/tomcat/tomcat-9/v${TOMCAT_VERSION}/bin/apache-tomcat-${TOMCAT_VERSION}.zip" cd bsbm-tools || exit ./generate -fc -pc ${DATASET_SIZE} -s nt -fn "explore-${DATASET_SIZE}" -ud -ufn "explore-update-${DATASET_SIZE}" wget -nc -O "rdf4j-${VERSION}.zip" "https://www.eclipse.org/downloads/download.php?file=/rdf4j/eclipse-rdf4j-${VERSION}-sdk.zip&mirror_id=1" unzip ../"rdf4j-${VERSION}.zip" unzip ../"tomcat-${TOMCAT_VERSION}.zip" CATALINA_HOME="$(pwd)/apache-tomcat-${TOMCAT_VERSION}" export CATALINA_HOME export JAVA_OPTS="-Dorg.eclipse.rdf4j.appdata.basedir=${CATALINA_HOME}/rdf4j" cp "eclipse-rdf4j-${VERSION}"/war/rdf4j-server.war "${CATALINA_HOME}"/webapps/ chmod +x "${CATALINA_HOME}"/bin/*.sh "${CATALINA_HOME}"/bin/startup.sh sleep 30 curl -f -X PUT http://localhost:8080/rdf4j-server/repositories/bsbm -H 'Content-Type:text/turtle' -d ' @prefix rdfs: . @prefix rep: . @prefix sr: . @prefix sail: . [] a rep:Repository ; rep:repositoryID "bsbm" ; rdfs:label "BSBM" ; rep:repositoryImpl [ rep:repositoryType "openrdf:SailRepository" ; sr:sailImpl [ sail:sailType "rdf4j:LmdbStore" ] ] . ' sleep 10 curl -f -X PUT -H 'Content-Type:application/n-triples' -T "explore-${DATASET_SIZE}.nt" http://localhost:8080/rdf4j-server/repositories/bsbm/statements ./testdriver -mt ${PARALLELISM} -ucf usecases/explore/sparql.txt -o "../bsbm.explore.rdf4j-lmdb.${VERSION}.${DATASET_SIZE}.${PARALLELISM}.xml" http://localhost:8080/rdf4j-server/repositories/bsbm ./testdriver -mt ${PARALLELISM} -ucf usecases/exploreAndUpdate/sparql.txt -o "../bsbm.exploreAndUpdate.rdf4j-lmdb.${VERSION}.${DATASET_SIZE}.${PARALLELISM}.xml" http://localhost:8080/rdf4j-server/repositories/bsbm -u http://localhost:8080/rdf4j-server/repositories/bsbm/statements -udataset "explore-update-${DATASET_SIZE}.nt" #./testdriver -mt ${PARALLELISM} -ucf usecases/businessIntelligence/sparql.txt -o "../bsbm.businessIntelligence.rdf4j-lmdb.${VERSION}.${DATASET_SIZE}.${PARALLELISM}.xml" http://localhost:8080/rdf4j-server/repositories/bsbm "${CATALINA_HOME}"/bin/shutdown.sh rm -f "explore-${DATASET_SIZE}.nt" rm -f "explore-update-${DATASET_SIZE}.nt" rm -rf td_data rm -rf "eclipse-rdf4j-${VERSION}" rm -rf "apache-tomcat-${TOMCAT_VERSION}" oxigraph-0.3.22/bench/bsbm_virtuoso.sh000077500000000000000000000027441453236674100177540ustar00rootroot00000000000000#!/usr/bin/env bash DATASET_SIZE=100000 # number of products in the dataset. There is around 350 triples generated by product. PARALLELISM=16 VERSION="7.2.5" set -eu cd bsbm-tools ./generate -fc -pc ${DATASET_SIZE} -s nt -fn "explore-${DATASET_SIZE}" -ud -ufn "explore-update-${DATASET_SIZE}" cp ../virtuoso-opensource/database/virtuoso.ini.sample virtuoso.ini mkdir ../database ../virtuoso-opensource/bin/virtuoso-t -f & sleep 10 ../virtuoso-opensource/bin/isql 1111 dba dba <; ld_dir('$(realpath .)', 'explore-${DATASET_SIZE}.nt', 'urn:graph:test'); rdf_loader_run(); EOF ./testdriver -mt ${PARALLELISM} -ucf usecases/explore/sparql.txt -o "../bsbm.explore.virtuoso.${VERSION}.${DATASET_SIZE}.${PARALLELISM}.xml" 'http://localhost:8890/sparql?graph-uri=urn:graph:test' # ./testdriver -mt ${PARALLELISM} -ucf usecases/exploreAndUpdate/sparql.txt -o "../bsbm.exploreAndUpdate.virtuoso.${DATASET_SIZE}.${PARALLELISM}.${PARALLELISM}.${VERSION}.xml" 'http://localhost:8890/sparql?graph-uri=urn:graph:test' -u 'http://dba:dba@localhost:8890/sparql-auth?graph-uri=urn:graph:test' -udataset "explore-update-${DATASET_SIZE}.nt" # ./testdriver -mt ${PARALLELISM} -ucf usecases/businessIntelligence/sparql.txt -o "../bsbm.businessIntelligence.virtuoso.${VERSION}.${DATASET_SIZE}.${PARALLELISM}.xml" 'http://localhost:8890/sparql?graph-uri=urn:graph:test' kill $! rm -rf ../database rm -f "explore-${DATASET_SIZE}.nt" rm -f "explore-update-${DATASET_SIZE}.nt" rm -rf td_data oxigraph-0.3.22/bench/explanation_to_flamegraph.py000066400000000000000000000045411453236674100223010ustar00rootroot00000000000000""" Converts a SPARQL query JSON explanation file to a flamegraph. Usage: python explanation_to_flamegraph.py explanation.json flamegraph.svg """ import json import subprocess from argparse import ArgumentParser from pathlib import Path from shutil import which from tempfile import NamedTemporaryFile parser = ArgumentParser( prog='OxigraphFlamegraph', description='Builds a flamegraph from the Oxigraph query explanation JSON format', epilog='Text at the bottom of help') parser.add_argument('json_explanation', type=Path) parser.add_argument('flamegraph_svg', type=Path) args = parser.parse_args() def trace_line(label: str, value: float): return f"{label} {int(value * 1_000_000)}" with args.json_explanation.open('rt') as fp: explanation = json.load(fp) trace = [] if "parsing duration in seconds" in explanation: trace.append(trace_line("parsing", explanation['parsing duration in seconds'])) if "planning duration in seconds" in explanation: trace.append(trace_line("planning", explanation['planning duration in seconds'])) already_used_names = {} def add_to_trace(node, path): path = f"{path};{node['name'].replace(' ', '`')}" if path in already_used_names: already_used_names[path] += 1 path = f"{path}`{already_used_names[path]}" else: already_used_names[path] = 0 samples = node['duration in seconds'] - sum(child['duration in seconds'] for child in node.get("children", ())) if int(samples * 1_000_000) > 0: trace.append(trace_line(path, samples)) for i, child in enumerate(node.get("children", ())): add_to_trace(child, path) add_to_trace(explanation["plan"], 'eval') inferno = which('inferno-flamegraph') flamegraph_pl = which('flamegraph.pl') if inferno: args.flamegraph_svg.write_text( subprocess.run([inferno], input='\n'.join(trace), stdout=subprocess.PIPE, text=True).stdout) elif flamegraph_pl: with NamedTemporaryFile('w+t') as fp: fp.write('\n'.join(trace)) fp.flush() args.flamegraph_svg.write_text( subprocess.run([flamegraph_pl, fp.name], stdout=subprocess.PIPE, text=True).stdout) else: raise Exception( 'This script requires either the inferno-flamegraph from https://github.com/jonhoo/inferno either the flamegraph.pl script from https://github.com/brendangregg/FlameGraph to be installed and be in $PATH.') oxigraph-0.3.22/bench/explanation_to_trace.py000066400000000000000000000033511453236674100212670ustar00rootroot00000000000000""" Converts a SPARQL query JSON explanation file to a tracing event file compatible with Chrome. Usage: python explanation_to_trace.py explanation.json trace.json """ import json from argparse import ArgumentParser from pathlib import Path parser = ArgumentParser( prog='OxigraphTracing', description='Builds a Trace Event Format file from the Oxigraph query explanation JSON format') parser.add_argument('json_explanation', type=Path) parser.add_argument('json_trace_event', type=Path) args = parser.parse_args() with args.json_explanation.open('rt') as fp: explanation = json.load(fp) trace = [] def trace_element(name: str, cat: str, start_s: float, duration_s: float): return { "name": name, "cat": cat, "ph": "X", "ts": int(start_s * 1_000_000), "dur": int(duration_s * 1_000_000), "pid": 1 } def add_to_trace(node, path, start_time: float): path = f"{path};{node['name'].replace(' ', '`')}" trace.append(trace_element(node["name"], node["name"].split("(")[0], start_time, node["duration in seconds"])) for child in node.get("children", ()): add_to_trace(child, path, start_time) start_time += child["duration in seconds"] current_time = 0 if "parsing duration in seconds" in explanation: d = explanation["parsing duration in seconds"] trace.append(trace_element(f"parsing", "parsing", current_time, d)) current_time += d if "planning duration in seconds" in explanation: d = explanation["planning duration in seconds"] trace.append(trace_element(f"planning", "planning", current_time, d)) current_time += d add_to_trace(explanation["plan"], 'eval', current_time) with args.json_trace_event.open("wt") as fp: json.dump(trace, fp) oxigraph-0.3.22/clippy.toml000066400000000000000000000002101453236674100156200ustar00rootroot00000000000000avoid-breaking-exported-api = true cognitive-complexity-threshold = 50 too-many-arguments-threshold = 10 type-complexity-threshold = 500oxigraph-0.3.22/deny.toml000066400000000000000000000005331453236674100152670ustar00rootroot00000000000000[licenses] unlicensed = "deny" allow = [ "MIT", "Apache-2.0", "Apache-2.0 WITH LLVM-exception" ] allow-osi-fsf-free = "either" default = "deny" [[licenses.clarify]] name = "ring" version = "*" expression = "MIT AND ISC AND OpenSSL" license-files = [ { path = "LICENSE", hash = 0xbd0eed23 } ] [sources] unknown-registry = "deny" oxigraph-0.3.22/fuzz/000077500000000000000000000000001453236674100144305ustar00rootroot00000000000000oxigraph-0.3.22/fuzz/.gitignore000066400000000000000000000000271453236674100164170ustar00rootroot00000000000000target corpus artifactsoxigraph-0.3.22/fuzz/Cargo.toml000066400000000000000000000017441453236674100163660ustar00rootroot00000000000000[package] name = "oxigraph-fuzz" version = "0.0.0" authors = ["Automatically generated"] publish = false edition = "2021" [package.metadata] cargo-fuzz = true [dependencies] anyhow = "1" lazy_static = "1" libfuzzer-sys = "0.4" spargebra = { path = "../lib/spargebra", features = ["rdf-star", "sep-0006"] } sparesults = { path = "../lib/sparesults", features = ["rdf-star"] } sparql-smith = { path = "../lib/sparql-smith", features = ["sep-0006"] } oxigraph = { path = "../lib" } [profile.release] codegen-units = 1 debug = true [workspace] [[bin]] name = "sparql_eval" path = "fuzz_targets/sparql_eval.rs" [[bin]] name = "sparql_query" path = "fuzz_targets/sparql_query.rs" [[bin]] name = "sparql_update" path = "fuzz_targets/sparql_update.rs" [[bin]] name = "sparql_results_json" path = "fuzz_targets/sparql_results_json.rs" [[bin]] name = "sparql_results_xml" path = "fuzz_targets/sparql_results_xml.rs" [[bin]] name = "sparql_results_tsv" path = "fuzz_targets/sparql_results_tsv.rs" oxigraph-0.3.22/fuzz/fuzz_targets/000077500000000000000000000000001453236674100171575ustar00rootroot00000000000000oxigraph-0.3.22/fuzz/fuzz_targets/sparql_eval.rs000066400000000000000000000040561453236674100220430ustar00rootroot00000000000000#![no_main] use lazy_static::lazy_static; use libfuzzer_sys::fuzz_target; use oxigraph::io::DatasetFormat; use oxigraph::sparql::{Query, QueryOptions, QueryResults, QuerySolutionIter}; use oxigraph::store::Store; lazy_static! { static ref STORE: Store = { let store = Store::new().unwrap(); store .load_dataset( sparql_smith::DATA_TRIG.as_bytes(), DatasetFormat::TriG, None, ) .unwrap(); store }; } fuzz_target!(|data: sparql_smith::Query| { let query_str = data.to_string(); if let Ok(query) = Query::parse(&query_str, None) { let options = QueryOptions::default(); let with_opt = STORE.query_opt(query.clone(), options.clone()).unwrap(); let without_opt = STORE .query_opt(query, options.without_optimizations()) .unwrap(); match (with_opt, without_opt) { (QueryResults::Solutions(with_opt), QueryResults::Solutions(without_opt)) => { assert_eq!( query_solutions_key(with_opt, query_str.contains(" REDUCED ")), query_solutions_key(without_opt, query_str.contains(" REDUCED ")) ) } (QueryResults::Graph(_), QueryResults::Graph(_)) => unimplemented!(), (QueryResults::Boolean(with_opt), QueryResults::Boolean(without_opt)) => { assert_eq!(with_opt, without_opt) } _ => panic!("Different query result types"), } } }); fn query_solutions_key(iter: QuerySolutionIter, is_reduced: bool) -> String { // TODO: ordering let mut b = iter .into_iter() .map(|t| { let mut b = t .unwrap() .iter() .map(|(var, val)| format!("{}: {}", var, val)) .collect::>(); b.sort_unstable(); b.join(" ") }) .collect::>(); b.sort_unstable(); if is_reduced { b.dedup(); } b.join("\n") } oxigraph-0.3.22/fuzz/fuzz_targets/sparql_query.rs000066400000000000000000000002011453236674100222450ustar00rootroot00000000000000#![no_main] use libfuzzer_sys::fuzz_target; use spargebra::Query; fuzz_target!(|data: &str| { Query::parse(data, None); }); oxigraph-0.3.22/fuzz/fuzz_targets/sparql_results_json.rs000066400000000000000000000003331453236674100236400ustar00rootroot00000000000000#![no_main] use libfuzzer_sys::fuzz_target; use oxigraph_fuzz::result_format::fuzz_result_format; use sparesults::QueryResultsFormat; fuzz_target!(|data: &[u8]| { fuzz_result_format(QueryResultsFormat::Json, data) }); oxigraph-0.3.22/fuzz/fuzz_targets/sparql_results_tsv.rs000066400000000000000000000003321453236674100235020ustar00rootroot00000000000000#![no_main] use libfuzzer_sys::fuzz_target; use oxigraph_fuzz::result_format::fuzz_result_format; use sparesults::QueryResultsFormat; fuzz_target!(|data: &[u8]| { fuzz_result_format(QueryResultsFormat::Tsv, data) }); oxigraph-0.3.22/fuzz/fuzz_targets/sparql_results_xml.rs000066400000000000000000000003321453236674100234660ustar00rootroot00000000000000#![no_main] use libfuzzer_sys::fuzz_target; use oxigraph_fuzz::result_format::fuzz_result_format; use sparesults::QueryResultsFormat; fuzz_target!(|data: &[u8]| { fuzz_result_format(QueryResultsFormat::Xml, data) }); oxigraph-0.3.22/fuzz/fuzz_targets/sparql_update.rs000066400000000000000000000002211453236674100223640ustar00rootroot00000000000000#![no_main] use libfuzzer_sys::fuzz_target; use spargebra::Update; use std::str; fuzz_target!(|data: &str| { Update::parse(data, None); }); oxigraph-0.3.22/fuzz/src/000077500000000000000000000000001453236674100152175ustar00rootroot00000000000000oxigraph-0.3.22/fuzz/src/lib.rs000066400000000000000000000000271453236674100163320ustar00rootroot00000000000000pub mod result_format; oxigraph-0.3.22/fuzz/src/result_format.rs000066400000000000000000000042351453236674100204570ustar00rootroot00000000000000use anyhow::Context; use sparesults::{ QueryResultsFormat, QueryResultsParser, QueryResultsReader, QueryResultsSerializer, }; pub fn fuzz_result_format(format: QueryResultsFormat, data: &[u8]) { let parser = QueryResultsParser::from_format(format); let serializer = QueryResultsSerializer::from_format(format); let Ok(reader) = parser.read_results(data) else { return; }; match reader { QueryResultsReader::Solutions(solutions) => { let Ok(solutions) = solutions.collect::, _>>() else { return; }; // We try to write again let mut writer = serializer .solutions_writer( Vec::new(), solutions .get(0) .map_or_else(Vec::new, |s| s.variables().to_vec()), ) .unwrap(); for solution in &solutions { writer.write(solution).unwrap(); } let serialized = String::from_utf8(writer.finish().unwrap()).unwrap(); // And to parse again if let QueryResultsReader::Solutions(roundtrip_solutions) = parser .read_results(serialized.as_bytes()) .with_context(|| format!("Parsing {:?}", &serialized)) .unwrap() { assert_eq!( roundtrip_solutions .collect::, _>>() .with_context(|| format!("Parsing {:?}", &serialized)) .unwrap(), solutions ) } } QueryResultsReader::Boolean(value) => { // We try to write again let mut serialized = Vec::new(); serializer .write_boolean_result(&mut serialized, value) .unwrap(); // And to parse again if let QueryResultsReader::Boolean(roundtrip_value) = parser.read_results(serialized.as_slice()).unwrap() { assert_eq!(roundtrip_value, value) } } } } oxigraph-0.3.22/js/000077500000000000000000000000001453236674100140465ustar00rootroot00000000000000oxigraph-0.3.22/js/Cargo.toml000066400000000000000000000010141453236674100157720ustar00rootroot00000000000000[package] name = "oxigraph_js" version = "0.3.22" authors = ["Tpt "] license = "MIT OR Apache-2.0" readme = "README.md" keywords = ["RDF", "N-Triples", "Turtle", "RDF/XML", "SPARQL"] repository = "https://github.com/oxigraph/oxigraph/tree/main/js" description = "JavaScript bindings of Oxigraph" edition = "2021" [lib] crate-type = ["cdylib"] name = "oxigraph" [dependencies] oxigraph = { version = "0.3.22", path="../lib" } wasm-bindgen = "0.2" js-sys = "0.3" console_error_panic_hook = "0.1" oxigraph-0.3.22/js/README.md000066400000000000000000000247461453236674100153420ustar00rootroot00000000000000Oxigraph for JavaScript ======================= [![npm](https://img.shields.io/npm/v/oxigraph)](https://www.npmjs.com/package/oxigraph) [![actions status](https://github.com/oxigraph/oxigraph/workflows/build/badge.svg)](https://github.com/oxigraph/oxigraph/actions) [![Gitter](https://badges.gitter.im/oxigraph/community.svg)](https://gitter.im/oxigraph/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) This package provides a JavaScript API on top of [Oxigraph](https://crates.io/crates/oxigraph), compiled with WebAssembly. Oxigraph is a graph database written in Rust implementing the [SPARQL](https://www.w3.org/TR/sparql11-overview/) standard. Oxigraph for JavaScript is a work in progress and currently offers a simple in-memory store with [SPARQL 1.1 Query](https://www.w3.org/TR/sparql11-query/) and [SPARQL 1.1 Update](https://www.w3.org/TR/sparql11-update/) capabilities. The store is also able to load RDF serialized in [Turtle](https://www.w3.org/TR/turtle/), [TriG](https://www.w3.org/TR/trig/), [N-Triples](https://www.w3.org/TR/n-triples/), [N-Quads](https://www.w3.org/TR/n-quads/) and [RDF/XML](https://www.w3.org/TR/rdf-syntax-grammar/). It is distributed using a [a NPM package](https://www.npmjs.com/package/oxigraph) that should work with Node.JS 12+ and modern web browsers compatible with WebAssembly. To install: ```bash npm install oxigraph ``` To load with Node.JS: ```js const oxigraph = require('oxigraph'); ``` or with ES modules: ```js import oxigraph from './node_modules/oxigraph/node.js'; ``` To load on an HTML web page (for [WebPack 5](https://webpack.js.org/) remove the ` ``` ## Node.JS Example Insert the triple ` "example"` and log the name of `` in SPARQL: ```js const oxigraph = require('oxigraph'); const store = new oxigraph.Store(); const ex = oxigraph.namedNode("http://example/"); const schemaName = oxigraph.namedNode("http://schema.org/name"); store.add(oxigraph.triple(ex, schemaName, oxigraph.literal("example"))); for (const binding of store.query("SELECT ?name WHERE { ?name }")) { console.log(binding.get("name").value); } ``` ## Web Example Insert the triple ` "example"` and log the name of `` in SPARQL: ```html ``` This example works with WebPack too if you remove the `
oxigraph-0.3.22/test_spec_links.py000066400000000000000000000040541453236674100172000ustar00rootroot00000000000000import re import sys from pathlib import Path from urllib.error import HTTPError from urllib.parse import urlsplit, urlunsplit from urllib.request import urlopen LINK_REGEXES = { r"\[[^]]+]\((https?://(w3c.github.io|www.w3.org)/[^)]+)\)", # Markdown r"<(https?://(w3c.github.io|www.w3.org)/[^>]+)>`_", # reStructuredText } base_path = Path(__file__).parent spec_cache = {} errors = set() for ext in ("md", "rs", "rst"): for file in Path(__file__).parent.rglob(f"*.{ext}"): content = file.read_text() for link_regex in LINK_REGEXES: for m in re.finditer(link_regex, content): url = m.group(1) (scheme, host, path, query, fragment) = urlsplit(url) if scheme != "https": errors.add(f"HTTP URL used by {url} in {file}") if query != "": errors.add(f"URL query used by {url} in {file}") if path.endswith(".html/"): errors.add(f".html/ used by {url} in {file}") base_url = urlunsplit(("https", host, path.rstrip("/"), "", "")) if base_url not in spec_cache: try: with urlopen(base_url) as response: spec_cache[base_url] = response.read().decode() except HTTPError as e: errors.add( f"Fetching {url} used in {file} return HTTP error: {e}" ) spec_content = spec_cache.get(base_url, "") if ( fragment != "" and re.search(rf"[iI][dD]\s*=\s*['\"]{fragment}['\"]", spec_content) is None ): errors.add( f"Fragment {fragment} of {url} used in {file} does not exist" ) print("Used specs:") for url in sorted(spec_cache.keys()): print(url) if errors: print() for error in sorted(errors): print(error, file=sys.stderr) exit(1) oxigraph-0.3.22/testsuite/000077500000000000000000000000001453236674100154635ustar00rootroot00000000000000oxigraph-0.3.22/testsuite/Cargo.toml000066400000000000000000000010201453236674100174040ustar00rootroot00000000000000[package] name = "oxigraph_testsuite" version = "0.0.0" authors = ["Tpt "] license = "MIT OR Apache-2.0" readme = "../README.md" repository = "https://github.com/oxigraph/oxigraph" description = """ Implementation of W3C testsuites for Oxigraph """ edition = "2021" publish = false [dependencies] anyhow = "1" clap = { version = "4", features = ["derive"] } time = { version = "0.3", features = ["formatting"] } oxigraph = { path = "../lib" } text-diff = "0.4" [dev-dependencies] criterion = "0.4" oxigraph-0.3.22/testsuite/oxigraph-tests/000077500000000000000000000000001453236674100204445ustar00rootroot00000000000000oxigraph-0.3.22/testsuite/oxigraph-tests/sparql-results/000077500000000000000000000000001453236674100234455ustar00rootroot00000000000000oxigraph-0.3.22/testsuite/oxigraph-tests/sparql-results/duplicated_variables.srj000066400000000000000000000003111453236674100303260ustar00rootroot00000000000000{ "head": { "vars": ["s", "p", "s"] }, "results": { "bindings": [ { "s": { "type": "uri", "value": "http://example.org/s1" } } ] } } oxigraph-0.3.22/testsuite/oxigraph-tests/sparql-results/duplicated_variables.srx000066400000000000000000000005231453236674100303510ustar00rootroot00000000000000 http://example.com/a oxigraph-0.3.22/testsuite/oxigraph-tests/sparql-results/duplicated_variables.tsv000066400000000000000000000000271453236674100303500ustar00rootroot00000000000000?s ?p ?s "s" "s" "s" oxigraph-0.3.22/testsuite/oxigraph-tests/sparql-results/ignored_keys.srj000066400000000000000000000003711453236674100266500ustar00rootroot00000000000000{ "head": { "vars": ["s"], "custom": null }, "results": { "custom": {"foo": [true, false]}, "bindings": [ { "s": { "type": "uri", "value": "http://example.org/s1" } } ] } } oxigraph-0.3.22/testsuite/oxigraph-tests/sparql-results/ignored_keys.srx000066400000000000000000000005131453236674100266640ustar00rootroot00000000000000 http://example.com/a oxigraph-0.3.22/testsuite/oxigraph-tests/sparql-results/late_head.srj000066400000000000000000000002731453236674100260750ustar00rootroot00000000000000{ "results": { "bindings": [ {}, { "s": { "type": "literal", "value": "foo" } } ] }, "head": { "vars": ["s"] } } oxigraph-0.3.22/testsuite/oxigraph-tests/sparql-results/late_head_expected.srj000066400000000000000000000002731453236674100277560ustar00rootroot00000000000000{ "head": { "vars": ["s"] }, "results": { "bindings": [ {}, { "s": { "type": "literal", "value": "foo" } } ] } } oxigraph-0.3.22/testsuite/oxigraph-tests/sparql-results/manifest.ttl000066400000000000000000000035421453236674100260040ustar00rootroot00000000000000@prefix rdf: . @prefix : . @prefix rdfs: . @prefix mf: . @prefix ox: . <> rdf:type mf:Manifest ; rdfs:label "Oxigraph SPARQL results tests" ; mf:entries ( :results_json_duplicated_variables :results_xml_duplicated_variables :results_tsv_duplicated_variables :results_json_ignored_keys :results_xml_ignored_keys :results_json_typed_literal :late_head ) . :results_json_duplicated_variables rdf:type ox:NegativeJsonResultsSyntaxTest ; mf:name "Duplicated variables are not allowed" ; mf:action . :results_xml_duplicated_variables rdf:type ox:NegativeXmlResultsSyntaxTest ; mf:name "Duplicated variables are not allowed" ; mf:action . :results_tsv_duplicated_variables rdf:type ox:NegativeTsvResultsSyntaxTest ; mf:name "Duplicated variables are not allowed" ; mf:action . :results_json_ignored_keys rdf:type ox:PositiveJsonResultsSyntaxTest ; mf:name "Ignore unknown keys in objects" ; mf:action . :results_xml_ignored_keys rdf:type ox:PositiveXmlResultsSyntaxTest ; mf:name "Ignore unknown attributes on tags" ; mf:action . :results_json_typed_literal rdf:type ox:PositiveJsonResultsSyntaxTest ; mf:name "typed-literal term type is allowed" ; mf:action ; mf:result . :late_head rdf:type ox:PositiveJsonResultsSyntaxTest ; mf:name "head after the list of results" ; mf:action ; mf:result . oxigraph-0.3.22/testsuite/oxigraph-tests/sparql-results/typed_literal.srj000066400000000000000000000003461453236674100270310ustar00rootroot00000000000000{ "head": { "vars": ["s"] }, "results": { "bindings": [ { "s": { "type": "typed-literal", "value": "foo", "datatype": "http://example.com/dt" } } ] } } oxigraph-0.3.22/testsuite/oxigraph-tests/sparql-results/typed_literal_expected.srj000066400000000000000000000003401453236674100307040ustar00rootroot00000000000000{ "head": { "vars": ["s"] }, "results": { "bindings": [ { "s": { "type": "literal", "value": "foo", "datatype": "http://example.com/dt" } } ] } } oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/000077500000000000000000000000001453236674100217465ustar00rootroot00000000000000oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/ask_from.rq000066400000000000000000000000461453236674100241130ustar00rootroot00000000000000ASK FROM WHERE { } oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/cmp_langString.rq000066400000000000000000000001501453236674100252550ustar00rootroot00000000000000SELECT ?a ?b ?o WHERE { VALUES (?a ?b) { ("a"@fr "b"@fr) ("a"@en "b"@fr) } BIND(?a < ?b AS ?o) }oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/cmp_langString.srx000066400000000000000000000013261453236674100254550ustar00rootroot00000000000000 a b true a b oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/describe.rq000066400000000000000000000001011453236674100240620ustar00rootroot00000000000000DESCRIBE oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/describe_input.ttl000066400000000000000000000004351453236674100254740ustar00rootroot00000000000000PREFIX schema: a schema:Person ; schema:name "test"@en ; schema:parent ; schema:child [ a schema:Person ] . a schema:Person ; schema:child .oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/describe_output.ttl000066400000000000000000000002621453236674100256730ustar00rootroot00000000000000PREFIX schema: a schema:Person ; schema:name "test"@en ; schema:parent ; schema:child [] . oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/describe_where.rq000066400000000000000000000000731453236674100252640ustar00rootroot00000000000000DESCRIBE ?s WHERE { ?s "test"@en }oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/group_concat_with_null.rq000066400000000000000000000001721453236674100270620ustar00rootroot00000000000000PREFIX : SELECT (GROUP_CONCAT(?opt) AS ?g) WHERE { ?baseS a :ex OPTIONAL { ?baseS :opt ?opt } }oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/group_concat_with_null.srx000066400000000000000000000004651453236674100272610ustar00rootroot00000000000000 value oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/group_concat_with_null.ttl000066400000000000000000000001141453236674100272370ustar00rootroot00000000000000@prefix : . :a a :ex ; :opt "value" . :b a :ex . oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/in_empty_error.rq000066400000000000000000000000541453236674100253460ustar00rootroot00000000000000SELECT ?r WHERE { BIND((?foo IN ()) AS ?r) }oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/in_empty_error.srx000066400000000000000000000003021453236674100255340ustar00rootroot00000000000000 oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/lateral/000077500000000000000000000000001453236674100233725ustar00rootroot00000000000000oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/lateral/basic_input.ttl000066400000000000000000000001711453236674100264160ustar00rootroot00000000000000@prefix ex: . ex:s1 a ex:T ; ex:p 11 , 12 , 13 . ex:s2 a ex:T ; ex:p 21 , 22 , 23 . ex:s3 a ex:T .oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/lateral/filter.rq000066400000000000000000000002451453236674100252240ustar00rootroot00000000000000PREFIX ex: SELECT ?s ?o WHERE { VALUES ?s { ex:S } LATERAL { VALUES ?o { ex:O } FILTER(BOUND(?s) && EXISTS { FILTER(BOUND(?s)) }) } } oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/lateral/graph.rq000066400000000000000000000002251453236674100250360ustar00rootroot00000000000000PREFIX ex: SELECT ?s ?o WHERE { VALUES ?s { ex:S } LATERAL { GRAPH ex:G { FILTER(BOUND(?s)) . VALUES ?o { ex:O } } } }oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/lateral/join.rq000066400000000000000000000002571453236674100247010ustar00rootroot00000000000000PREFIX ex: SELECT ?s ?o WHERE { VALUES ?s { ex:S } LATERAL { { VALUES ?o { ex:O } } { FILTER(BOUND(?s) && !BOUND(?o)) } } } oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/lateral/manifest.ttl000066400000000000000000000044431453236674100257320ustar00rootroot00000000000000@prefix rdf: . @prefix : . @prefix rdfs: . @prefix mf: . @prefix qt: . @prefix ut: . <> rdf:type mf:Manifest ; rdfs:label "Oxigraph LATERAL feature SPARQL tests" ; mf:entries ( :subselect :subselect_inside_optional :subselect_outside_optional :subselect_aggregate :optional :graph :filter :join ) . :subselect rdf:type mf:QueryEvaluationTest ; mf:name "Basic subselect LATERAL test" ; mf:action [ qt:query ; qt:data ] ; mf:result . :subselect_inside_optional rdf:type mf:QueryEvaluationTest ; mf:name "Basic subselect LATERAL test inside OPTIONAL" ; mf:action [ qt:query ; qt:data ] ; mf:result . :subselect_outside_optional rdf:type mf:QueryEvaluationTest ; mf:name "Basic subselect test inside LATERAL OPTIONAL" ; mf:action [ qt:query ; qt:data ] ; mf:result . :subselect_aggregate rdf:type mf:QueryEvaluationTest ; mf:name "LATERAL test with explicit aggregate" ; mf:action [ qt:query ; qt:data ] ; mf:result . :optional rdf:type mf:QueryEvaluationTest ; mf:name "LATERAL OPTIONAL test" ; mf:action [ qt:query ] ; mf:result . :graph rdf:type mf:QueryEvaluationTest ; mf:name "LATERAL GRAPH test" ; mf:action [ qt:query ] ; mf:result . :filter rdf:type mf:QueryEvaluationTest ; mf:name "LATERAL FILTER test" ; mf:action [ qt:query ] ; mf:result . :join rdf:type mf:QueryEvaluationTest ; mf:name "join in LATERAL test" ; mf:action [ qt:query ] ; mf:result . oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/lateral/optional.rq000066400000000000000000000002231453236674100255600ustar00rootroot00000000000000PREFIX ex: SELECT ?s ?o WHERE { VALUES ?s { ex:S } LATERAL { OPTIONAL { FILTER(BOUND(?s)) . VALUES ?o { ex:O } } } }oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/lateral/simple.srx000066400000000000000000000005641453236674100254260ustar00rootroot00000000000000 http://example.org/S http://example.org/O oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/lateral/subselect.rq000066400000000000000000000002131453236674100257230ustar00rootroot00000000000000PREFIX ex: SELECT ?s ?o WHERE { ?s a ex:T. LATERAL {SELECT ?s ?o WHERE { ?s ex:p ?o } ORDER BY ?o LIMIT 2} }oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/lateral/subselect.srx000066400000000000000000000021351453236674100261220ustar00rootroot00000000000000 http://example.org/s1 11 http://example.org/s1 12 http://example.org/s2 21 http://example.org/s2 22 oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/lateral/subselect_aggregate.rq000066400000000000000000000002201453236674100277270ustar00rootroot00000000000000PREFIX ex: SELECT ?s ?c WHERE { ?s a ex:T. LATERAL {SELECT ?s (MAX(?o) AS ?c) WHERE { ?s ex:p ?o } GROUP BY ?s} }oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/lateral/subselect_aggregate.srx000066400000000000000000000012111453236674100301220ustar00rootroot00000000000000 http://example.org/s1 13 http://example.org/s2 23 oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/lateral/subselect_inside_optional.rq000066400000000000000000000002301453236674100311620ustar00rootroot00000000000000PREFIX ex: SELECT ?s ?o WHERE { ?s a ex:T. OPTIONAL { LATERAL {SELECT ?s ?o WHERE { ?s ex:p ?o } ORDER BY ?o LIMIT 2} } }oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/lateral/subselect_inside_optional.srx000066400000000000000000000015451453236674100313660ustar00rootroot00000000000000 http://example.org/s1 11 http://example.org/s1 12 http://example.org/s2 http://example.org/s3 oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/lateral/subselect_outside_optional.rq000066400000000000000000000002301453236674100313630ustar00rootroot00000000000000PREFIX ex: SELECT ?s ?o WHERE { ?s a ex:T. LATERAL { OPTIONAL {SELECT ?s ?o WHERE { ?s ex:p ?o } ORDER BY ?o LIMIT 2} } }oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/lateral/subselect_outside_optional.srx000066400000000000000000000023131453236674100315610ustar00rootroot00000000000000 http://example.org/s1 11 http://example.org/s1 12 http://example.org/s2 21 http://example.org/s2 22 http://example.org/s3 oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/long_unicode_escape_with_multibytes_char.rq000066400000000000000000000000071453236674100326050ustar00rootroot00000000000000\up6/È…oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/long_unicode_escape_with_multibytes_char.ru000066400000000000000000000000071453236674100326110ustar00rootroot00000000000000\up6/È…oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/manifest.ttl000066400000000000000000000141021453236674100242770ustar00rootroot00000000000000@prefix rdf: . @prefix : . @prefix rdfs: . @prefix mf: . @prefix qt: . @prefix ut: . <> rdf:type mf:Manifest ; rdfs:label "Oxigraph SPARQL tests" ; mf:include ( ) ; mf:entries ( :small_unicode_escape_with_multibytes_char :long_unicode_escape_with_multibytes_char :small_unicode_escape_with_multibytes_char_update :long_unicode_escape_with_multibytes_char_update :describe :describe_where :ask_with_from :group_concat_with_null :single_not_exists :property_list_path :values_in_filter_exists :values_in_filter_not_exists :subquery_in_filter_not_exists :cmp_langString :nested_path :nested_expression :order_terms :nested_anonymous :unbound_variable_in_subquery :one_or_more_shared :one_or_more_star :in_empty_error :small_iri_str ) . :small_unicode_escape_with_multibytes_char rdf:type mf:NegativeSyntaxTest ; mf:name "Multibytes character at the end of a unicode escape sequence" ; mf:action . :long_unicode_escape_with_multibytes_char rdf:type mf:NegativeSyntaxTest ; mf:name "Multibytes character at the end of a unicode escape sequence" ; mf:action . :small_unicode_escape_with_multibytes_char_update rdf:type mf:NegativeUpdateSyntaxTest11 ; mf:name "Multibytes character at the end of a unicode escape sequence" ; mf:action . :long_unicode_escape_with_multibytes_char_update rdf:type mf:NegativeUpdateSyntaxTest11 ; mf:name "Multibytes character at the end of a unicode escape sequence" ; mf:action . :describe rdf:type mf:QueryEvaluationTest ; mf:name "Simple DESCRIBE request" ; mf:action [ qt:query ; qt:data ] ; mf:result . :describe_where rdf:type mf:QueryEvaluationTest ; mf:name "Simple DESCRIBE request" ; mf:action [ qt:query ; qt:data ] ; mf:result . :ask_with_from rdf:type mf:PositiveSyntaxTest ; mf:name "ASK with FROM" ; mf:action . :group_concat_with_null rdf:type mf:QueryEvaluationTest ; mf:name "GROUP_CONCAT with NULL" ; rdfs:comment "GROUP_CONCAT should ignore null values" ; mf:action [ qt:query ; qt:data ] ; mf:result . :single_not_exists rdf:type mf:QueryEvaluationTest ; mf:name "query with only a FILTER NOT EXISTS" ; mf:action [ qt:query ; qt:data ] ; mf:result . :property_list_path rdf:type mf:PositiveSyntaxTest ; mf:name "PropertyListPathNotEmpty children should be ObjectListPath for consistency" ; mf:action . :values_in_filter_exists rdf:type mf:QueryEvaluationTest ; mf:name "VALUES inside of FILTER EXISTS" ; mf:action [ qt:query ] ; mf:result . :values_in_filter_not_exists rdf:type mf:QueryEvaluationTest ; mf:name "VALUES inside of FILTER EXISTS" ; mf:action [ qt:query ] ; mf:result . :subquery_in_filter_not_exists rdf:type mf:QueryEvaluationTest ; mf:name "VALUES inside of FILTER EXISTS" ; mf:action [ qt:query ] ; mf:result . :cmp_langString rdf:type mf:QueryEvaluationTest ; mf:name "rdf:langString with the same language are comparable" ; mf:action [ qt:query ] ; mf:result . :nested_path rdf:type mf:PositiveSyntaxTest11 ; mf:name "A very nested property path" ; mf:action . :nested_expression rdf:type mf:PositiveSyntaxTest11 ; mf:name "A very nested expression" ; mf:action . :order_terms rdf:type mf:QueryEvaluationTest ; mf:name "literals have an order for ORDER BY" ; mf:action [ qt:query ] ; mf:result . :nested_anonymous rdf:type mf:QueryEvaluationTest ; mf:name "Nested anonymous" ; mf:action [ qt:query ; qt:data ] ; mf:result . :unbound_variable_in_subquery rdf:type mf:QueryEvaluationTest ; mf:name "Variable should stay not bound in subqueries even if they are bound in the parent query" ; mf:action [ qt:query ] ; mf:result . :one_or_more_shared rdf:type mf:QueryEvaluationTest ; mf:name "SPARQL one or more with shared variable" ; mf:action [ qt:query ; qt:data ] ; mf:result . :one_or_more_star rdf:type mf:QueryEvaluationTest ; mf:name "SPARQL-star one or more with shared variable" ; mf:action [ qt:query ; qt:data ] ; mf:result . :in_empty_error rdf:type mf:QueryEvaluationTest ; mf:name "IN should propagate errors on the left side, even on the empty input" ; mf:action [ qt:query ] ; mf:result . :small_iri_str rdf:type mf:QueryEvaluationTest ; mf:name "Small IRI strings should be properly equal to their value" ; mf:action [ qt:query ] ; mf:result . oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/nested_anonymous.rq000066400000000000000000000001241453236674100257010ustar00rootroot00000000000000PREFIX : SELECT ?a WHERE { [ :p1 ?a ; :p2 [ :p3 :foo ] ] }oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/nested_anonymous.srx000066400000000000000000000003771453236674100261050ustar00rootroot00000000000000 t1 oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/nested_anonymous.ttl000066400000000000000000000001441453236674100260640ustar00rootroot00000000000000PREFIX : [ :p1 "t1" ; :p2 [ :p3 :foo ] ] . [ :p1 "t2" ; :p2 [ :p3 :bar ] ] . oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/nested_expression.rq000066400000000000000000000002611453236674100260520ustar00rootroot00000000000000SELECT * WHERE { ?s ?p ?o . FILTER((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((true)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) } oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/nested_path.rq000066400000000000000000000004621453236674100246120ustar00rootroot00000000000000SELECT * WHERE { ?s (((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((()))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) ?o } oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/one_or_more_shared.rq000066400000000000000000000001051453236674100261370ustar00rootroot00000000000000PREFIX ex: SELECT * WHERE { ?s ex:p+ ?s } oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/one_or_more_shared.srx000066400000000000000000000005661453236674100263440ustar00rootroot00000000000000 http://example.org/s http://example.org/m oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/one_or_more_shared.ttl000066400000000000000000000001211453236674100263160ustar00rootroot00000000000000@prefix ex: . ex:s ex:p ex:m . ex:m ex:p ex:s , ex:sbis . oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/one_or_more_star.rq000066400000000000000000000001431453236674100256440ustar00rootroot00000000000000PREFIX ex: SELECT * WHERE { << ?s ex:p ex:o >> ex:p+ << ?s ex:p ?o >> } oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/one_or_more_star.srx000066400000000000000000000005651453236674100260460ustar00rootroot00000000000000 http://example.org/s http://example.org/oa oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/one_or_more_star.ttl000066400000000000000000000002031453236674100260220ustar00rootroot00000000000000@prefix ex: . << ex:s ex:p ex:o >> ex:p ex:m . ex:m ex:p << ex:s ex:p ex:oa >> , << ex:sbis ex:p ex:oa >> . oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/order_terms.rq000066400000000000000000000003641453236674100246420ustar00rootroot00000000000000SELECT ?o WHERE { VALUES ?o { 4.0 "v" "u"@en "a" "d"@de "c"@en "b" "foo"^^ 1 "2021-30-30"^^ "2020-30-29T00:00:00"^^ -1e3 } } ORDER BY ?ooxigraph-0.3.22/testsuite/oxigraph-tests/sparql/order_terms.ttl000066400000000000000000000047641453236674100250330ustar00rootroot00000000000000@prefix rdf: . @prefix rs: . [] rdf:type rs:ResultSet ; rs:resultVariable "o" ; rs:solution [ rs:binding [ rs:value -1e3 ; rs:variable "o" ] ; rs:index 1 ] ; rs:solution [ rs:binding [ rs:value 1 ; rs:variable "o" ] ; rs:index 2 ] ; rs:solution [ rs:binding [ rs:value "2020-30-29T00:00:00"^^ ; rs:variable "o" ] ; rs:index 3 ] ; rs:solution [ rs:binding [ rs:value "2021-30-30"^^ ; rs:variable "o" ] ; rs:index 4 ] ; rs:solution [ rs:binding [ rs:value 4.0 ; rs:variable "o" ] ; rs:index 5 ] ; rs:solution [ rs:binding [ rs:value "a" ; rs:variable "o" ] ; rs:index 6 ] ; rs:solution [ rs:binding [ rs:value "b" ; rs:variable "o" ] ; rs:index 7 ] ; rs:solution [ rs:binding [ rs:value "c"@en ; rs:variable "o" ] ; rs:index 8 ] ; rs:solution [ rs:binding [ rs:value "d"@de ; rs:variable "o" ] ; rs:index 9 ] ; rs:solution [ rs:binding [ rs:value "foo"^^ ; rs:variable "o" ] ; rs:index 10 ] ; rs:solution [ rs:binding [ rs:value "u"@en ; rs:variable "o" ] ; rs:index 11 ] ; rs:solution [ rs:binding [ rs:value "v" ; rs:variable "o" ] ; rs:index 12 ] . oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/property_list_path.rq000066400000000000000000000001341453236674100262430ustar00rootroot00000000000000PREFIX ex: SELECT ?o WHERE { ?s a ex:A ; ex:p [ ex:p1/ex:p2 ?o ] } oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/single_not_exists.rq000066400000000000000000000000611453236674100260470ustar00rootroot00000000000000SELECT * WHERE { FILTER NOT EXISTS { ?s ?p ?o } }oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/single_not_exists.srx000066400000000000000000000002031453236674100262370ustar00rootroot00000000000000 oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/small_iri_str.rq000066400000000000000000000000501453236674100251500ustar00rootroot00000000000000ASK { FILTER(STR() = "ex:a") }oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/small_iri_str.srx000066400000000000000000000002041453236674100253430ustar00rootroot00000000000000 true oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/small_unicode_escape_with_multibytes_char.rq000066400000000000000000000000131453236674100327530ustar00rootroot00000000000000\U0000p6/È…oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/small_unicode_escape_with_multibytes_char.ru000066400000000000000000000000131453236674100327570ustar00rootroot00000000000000\U0000p6/È…oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/subquery_in_filter_not_exists.rq000066400000000000000000000002251453236674100305020ustar00rootroot00000000000000PREFIX ex: SELECT ?s WHERE { VALUES ?s { ex:a ex:b } FILTER NOT EXISTS { {SELECT ?s WHERE { VALUES ?s { ex:b } }} } } oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/unbound_variable_in_subquery.rq000066400000000000000000000002131453236674100302520ustar00rootroot00000000000000PREFIX ex: SELECT ?a ?b WHERE { BIND(ex:a as ?a) {SELECT ?b WHERE { BIND(ex:b as ?b) FILTER(!BOUND(?a))}} } oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/unbound_variable_in_subquery.srx000066400000000000000000000006641453236674100304560ustar00rootroot00000000000000 http://example.com/a http://example.com/b oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/values_in_filter_exists.rq000066400000000000000000000002001453236674100272330ustar00rootroot00000000000000PREFIX ex: SELECT ?s WHERE { VALUES ?s { ex:a ex:b } FILTER EXISTS { VALUES ?s { ex:a ex:c } } } oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/values_in_filter_exists.srx000066400000000000000000000004111453236674100274310ustar00rootroot00000000000000 http://example.com/a oxigraph-0.3.22/testsuite/oxigraph-tests/sparql/values_in_filter_not_exists.rq000066400000000000000000000001771453236674100301300ustar00rootroot00000000000000PREFIX ex: SELECT ?s WHERE { VALUES ?s { ex:a ex:b } FILTER NOT EXISTS { VALUES ?s { ex:b } } } oxigraph-0.3.22/testsuite/rdf-star/000077500000000000000000000000001453236674100172055ustar00rootroot00000000000000oxigraph-0.3.22/testsuite/rdf-tests/000077500000000000000000000000001453236674100173765ustar00rootroot00000000000000oxigraph-0.3.22/testsuite/src/000077500000000000000000000000001453236674100162525ustar00rootroot00000000000000oxigraph-0.3.22/testsuite/src/evaluator.rs000066400000000000000000000022171453236674100206240ustar00rootroot00000000000000use crate::manifest::Test; use crate::report::TestResult; use anyhow::{anyhow, Result}; use std::collections::HashMap; use time::OffsetDateTime; #[derive(Default)] pub struct TestEvaluator { handlers: HashMap Result<()>>>, } impl TestEvaluator { pub fn register( &mut self, test_type: impl Into, handler: impl Fn(&Test) -> Result<()> + 'static, ) { self.handlers.insert(test_type.into(), Box::new(handler)); } pub fn evaluate( &self, manifest: impl Iterator>, ) -> Result> { manifest .map(|test| { let test = test?; let outcome = if let Some(handler) = self.handlers.get(test.kind.as_str()) { handler(&test) } else { Err(anyhow!("The test type {} is not supported", test.kind)) }; Ok(TestResult { test: test.id, outcome, date: OffsetDateTime::now_utc(), }) }) .collect() } } oxigraph-0.3.22/testsuite/src/files.rs000066400000000000000000000047651453236674100177360ustar00rootroot00000000000000use anyhow::{anyhow, bail, Result}; use oxigraph::io::{DatasetFormat, DatasetParser, GraphFormat, GraphParser}; use oxigraph::model::{Dataset, Graph}; use std::fs::File; use std::io::{BufRead, BufReader, Read}; use std::path::PathBuf; pub fn read_file(url: &str) -> Result { let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); path.push(if url.starts_with("http://w3c.github.io/") { url.replace("http://w3c.github.io/", "") } else if url.starts_with("https://w3c.github.io/") { url.replace("https://w3c.github.io/", "") } else if url.starts_with("http://www.w3.org/2013/RDFXMLTests/") { url.replace("http://www.w3.org/2013/RDFXMLTests/", "rdf-tests/rdf-xml/") } else if url.starts_with("https://github.com/oxigraph/oxigraph/tests/") { url.replace( "https://github.com/oxigraph/oxigraph/tests/", "oxigraph-tests/", ) } else { bail!("Not supported url for file: {url}") }); Ok(BufReader::new(File::open(&path)?)) } pub fn read_file_to_string(url: &str) -> Result { let mut buf = String::new(); read_file(url)?.read_to_string(&mut buf)?; Ok(buf) } pub fn load_to_graph(url: &str, graph: &mut Graph, format: GraphFormat) -> Result<()> { let parser = GraphParser::from_format(format).with_base_iri(url)?; for t in parser.read_triples(read_file(url)?)? { graph.insert(&t?); } Ok(()) } pub fn load_graph(url: &str, format: GraphFormat) -> Result { let mut graph = Graph::new(); load_to_graph(url, &mut graph, format)?; Ok(graph) } pub fn guess_graph_format(url: &str) -> Result { url.rsplit_once('.') .and_then(|(_, extension)| GraphFormat::from_extension(extension)) .ok_or_else(|| anyhow!("Serialization type not found for {url}")) } pub fn load_to_dataset(url: &str, dataset: &mut Dataset, format: DatasetFormat) -> Result<()> { let parser = DatasetParser::from_format(format).with_base_iri(url)?; for q in parser.read_quads(read_file(url)?)? { dataset.insert(&q?); } Ok(()) } pub fn load_dataset(url: &str, format: DatasetFormat) -> Result { let mut dataset = Dataset::new(); load_to_dataset(url, &mut dataset, format)?; Ok(dataset) } pub fn guess_dataset_format(url: &str) -> Result { url.rsplit_once('.') .and_then(|(_, extension)| DatasetFormat::from_extension(extension)) .ok_or_else(|| anyhow!("Serialization type not found for {url}")) } oxigraph-0.3.22/testsuite/src/lib.rs000066400000000000000000000003531453236674100173670ustar00rootroot00000000000000//! Implementation of [W3C RDF tests](https://w3c.github.io/rdf-tests/) to tests Oxigraph conformance. pub mod evaluator; pub mod files; pub mod manifest; pub mod parser_evaluator; pub mod report; pub mod sparql_evaluator; mod vocab; oxigraph-0.3.22/testsuite/src/main.rs000066400000000000000000000015101453236674100175410ustar00rootroot00000000000000#![allow(clippy::print_stdout)] use anyhow::Result; use clap::Parser; use oxigraph_testsuite::evaluator::TestEvaluator; use oxigraph_testsuite::manifest::TestManifest; use oxigraph_testsuite::parser_evaluator::register_parser_tests; use oxigraph_testsuite::report::build_report; use oxigraph_testsuite::sparql_evaluator::register_sparql_tests; #[derive(Parser)] /// Oxigraph testsuite runner struct Args { /// URI of the testsuite manifest(s) to run manifest: Vec, } fn main() -> Result<()> { let matches = Args::parse(); let mut evaluator = TestEvaluator::default(); register_parser_tests(&mut evaluator); register_sparql_tests(&mut evaluator); let manifest = TestManifest::new(matches.manifest); let results = evaluator.evaluate(manifest)?; print!("{}", build_report(results)); Ok(()) } oxigraph-0.3.22/testsuite/src/manifest.rs000066400000000000000000000325161453236674100204350ustar00rootroot00000000000000use crate::files::{guess_graph_format, load_to_graph}; use crate::vocab::*; use anyhow::{bail, Result}; use oxigraph::model::vocab::*; use oxigraph::model::*; use std::collections::VecDeque; use std::fmt; pub struct Test { pub id: NamedNode, pub kind: NamedNode, pub name: Option, pub comment: Option, pub action: Option, pub query: Option, pub update: Option, pub data: Option, pub graph_data: Vec<(NamedNode, String)>, pub service_data: Vec<(String, String)>, pub result: Option, pub result_graph_data: Vec<(NamedNode, String)>, } impl fmt::Display for Test { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.kind)?; for name in &self.name { write!(f, " named \"{name}\"")?; } for comment in &self.comment { write!(f, " with comment \"{comment}\"")?; } if let Some(action) = &self.action { write!(f, " on file \"{action}\"")?; } if let Some(query) = &self.query { write!(f, " on query {}", &query)?; } for data in &self.data { write!(f, " with data {data}")?; } for (_, data) in &self.graph_data { write!(f, " and graph data {data}")?; } for result in &self.result { write!(f, " and expected result {result}")?; } Ok(()) } } pub struct TestManifest { graph: Graph, tests_to_do: VecDeque, manifests_to_do: VecDeque, } impl Iterator for TestManifest { type Item = Result; fn next(&mut self) -> Option> { loop { if let Some(next) = self.next_test().transpose() { return Some(next); } if let Err(e) = self.load_next_manifest().transpose()? { return Some(Err(e)); } } } } impl TestManifest { pub fn new(manifest_urls: impl IntoIterator) -> Self { Self { graph: Graph::new(), tests_to_do: VecDeque::new(), manifests_to_do: manifest_urls .into_iter() .map(|url| url.to_string()) .collect(), } } fn next_test(&mut self) -> Result> { loop { let test_node = if let Some(test_node) = self.tests_to_do.pop_front() { test_node } else { return Ok(None); }; let test_node = if let Term::NamedNode(test_node) = test_node { test_node } else { bail!("Invalid test identifier. Got {test_node}"); }; if self .graph .contains(TripleRef::new(&test_node, rdft::APPROVAL, rdft::REJECTED)) { continue; // We do not run rejected tests } let name = if let Some(TermRef::Literal(c)) = self .graph .object_for_subject_predicate(&test_node, mf::NAME) { Some(c.value().to_owned()) } else { None }; let kind = if let Some(TermRef::NamedNode(c)) = self .graph .object_for_subject_predicate(&test_node, rdf::TYPE) { c.into_owned() } else { bail!( "The test {test_node} named {} has no rdf:type", name.as_deref().unwrap_or("") ); }; let comment = if let Some(TermRef::Literal(c)) = self .graph .object_for_subject_predicate(&test_node, rdfs::COMMENT) { Some(c.value().to_owned()) } else { None }; let (action, query, update, data, graph_data, service_data) = match self .graph .object_for_subject_predicate(&test_node, mf::ACTION) { Some(TermRef::NamedNode(n)) => ( Some(n.as_str().to_owned()), None, None, None, vec![], vec![], ), Some(TermRef::BlankNode(n)) => { let query = match self.graph.object_for_subject_predicate(n, qt::QUERY) { Some(TermRef::NamedNode(q)) => Some(q.as_str().to_owned()), _ => None, }; let update = match self.graph.object_for_subject_predicate(n, ut::REQUEST) { Some(TermRef::NamedNode(q)) => Some(q.as_str().to_owned()), _ => None, }; let data = match self .graph .object_for_subject_predicate(n, qt::DATA) .or_else(|| self.graph.object_for_subject_predicate(n, ut::DATA)) { Some(TermRef::NamedNode(q)) => Some(q.as_str().to_owned()), _ => None, }; let graph_data = self .graph .objects_for_subject_predicate(n, qt::GRAPH_DATA) .chain(self.graph.objects_for_subject_predicate(n, ut::GRAPH_DATA)) .filter_map(|g| match g { TermRef::NamedNode(q) => Some((q.into_owned(), q.as_str().to_owned())), TermRef::BlankNode(node) => { if let Some(TermRef::NamedNode(graph)) = self.graph.object_for_subject_predicate(node, ut::GRAPH) { if let Some(TermRef::Literal(name)) = self.graph.object_for_subject_predicate(node, rdfs::LABEL) { Some(( NamedNode::new(name.value()).unwrap(), graph.as_str().to_owned(), )) } else { Some((graph.into_owned(), graph.as_str().to_owned())) } } else { None } } _ => None, }) .collect(); let service_data = self .graph .objects_for_subject_predicate(n, qt::SERVICE_DATA) .filter_map(|g| match g { TermRef::NamedNode(g) => Some(g.into()), TermRef::BlankNode(g) => Some(g.into()), _ => None, }) .filter_map(|g: SubjectRef<'_>| { if let ( Some(TermRef::NamedNode(endpoint)), Some(TermRef::NamedNode(data)), ) = ( self.graph.object_for_subject_predicate(g, qt::ENDPOINT), self.graph.object_for_subject_predicate(g, qt::DATA), ) { Some((endpoint.as_str().to_owned(), data.as_str().to_owned())) } else { None } }) .collect(); (None, query, update, data, graph_data, service_data) } Some(_) => bail!("invalid action"), None => { bail!("action not found for test {test_node}"); } }; let (result, result_graph_data) = match self .graph .object_for_subject_predicate(&test_node, mf::RESULT) { Some(TermRef::NamedNode(n)) => (Some(n.as_str().to_owned()), Vec::new()), Some(TermRef::BlankNode(n)) => ( if let Some(TermRef::NamedNode(result)) = self.graph.object_for_subject_predicate(n, ut::DATA) { Some(result.as_str().to_owned()) } else { None }, self.graph .objects_for_subject_predicate(n, ut::GRAPH_DATA) .filter_map(|g| match g { TermRef::NamedNode(q) => Some((q.into_owned(), q.as_str().to_owned())), TermRef::BlankNode(node) => { if let Some(TermRef::NamedNode(graph)) = self.graph.object_for_subject_predicate(node, ut::GRAPH) { if let Some(TermRef::Literal(name)) = self.graph.object_for_subject_predicate(node, rdfs::LABEL) { Some(( NamedNode::new(name.value()).unwrap(), graph.as_str().to_owned(), )) } else { Some((graph.into_owned(), graph.as_str().to_owned())) } } else { None } } _ => None, }) .collect(), ), Some(_) => bail!("invalid result"), None => (None, Vec::new()), }; return Ok(Some(Test { id: test_node, kind, name, comment, action, query, update, data, graph_data, service_data, result, result_graph_data, })); } } fn load_next_manifest(&mut self) -> Result> { let url = if let Some(url) = self.manifests_to_do.pop_front() { url } else { return Ok(None); }; self.graph.clear(); load_to_graph(&url, &mut self.graph, guess_graph_format(&url)?)?; let manifests = self .graph .subjects_for_predicate_object(rdf::TYPE, mf::MANIFEST) .collect::>(); if manifests.len() != 1 { bail!("The file {url} should contain a single manifest"); } for manifest in manifests { match self .graph .object_for_subject_predicate(manifest, mf::INCLUDE) { Some(TermRef::BlankNode(list)) => { self.manifests_to_do.extend( RdfListIterator::iter(&self.graph, list.into()).filter_map(|m| match m { Term::NamedNode(nm) => Some(nm.into_string()), _ => None, }), ); } Some(_) => bail!("invalid tests list"), None => (), } // New tests match self .graph .object_for_subject_predicate(manifest, mf::ENTRIES) { Some(TermRef::BlankNode(list)) => { self.tests_to_do .extend(RdfListIterator::iter(&self.graph, list.into())); } Some(term) => { bail!("Invalid tests list. Got term {term}"); } None => (), } } Ok(Some(())) } } struct RdfListIterator<'a> { graph: &'a Graph, current_node: Option>, } impl<'a> RdfListIterator<'a> { fn iter(graph: &'a Graph, root: SubjectRef<'a>) -> RdfListIterator<'a> { RdfListIterator { graph, current_node: Some(root), } } } impl<'a> Iterator for RdfListIterator<'a> { type Item = Term; fn next(&mut self) -> Option { match self.current_node { Some(current) => { let result = self .graph .object_for_subject_predicate(current, rdf::FIRST) .map(TermRef::into_owned); self.current_node = match self.graph.object_for_subject_predicate(current, rdf::REST) { Some(TermRef::NamedNode(n)) if n == rdf::NIL => None, Some(TermRef::NamedNode(n)) => Some(n.into()), Some(TermRef::BlankNode(n)) => Some(n.into()), _ => None, }; result } None => None, } } } oxigraph-0.3.22/testsuite/src/parser_evaluator.rs000066400000000000000000000131451453236674100222020ustar00rootroot00000000000000use crate::evaluator::TestEvaluator; use crate::files::{guess_dataset_format, guess_graph_format, load_dataset, load_graph}; use crate::manifest::Test; use crate::report::{dataset_diff, graph_diff}; use anyhow::{anyhow, bail, Result}; use oxigraph::io::{DatasetFormat, GraphFormat}; pub fn register_parser_tests(evaluator: &mut TestEvaluator) { evaluator.register( "http://www.w3.org/ns/rdftest#TestNTriplesPositiveSyntax", |t| evaluate_positive_graph_syntax_test(t, GraphFormat::NTriples), ); evaluator.register( "http://www.w3.org/ns/rdftest#TestNQuadsPositiveSyntax", |t| evaluate_positive_dataset_syntax_test(t, DatasetFormat::NQuads), ); evaluator.register( "http://www.w3.org/ns/rdftest#TestTurtlePositiveSyntax", |t| evaluate_positive_graph_syntax_test(t, GraphFormat::Turtle), ); evaluator.register("http://www.w3.org/ns/rdftest#TestTrigPositiveSyntax", |t| { evaluate_positive_dataset_syntax_test(t, DatasetFormat::TriG) }); evaluator.register( "http://www.w3.org/ns/rdftest#TestNTriplesNegativeSyntax", |t| evaluate_negative_graph_syntax_test(t, GraphFormat::NTriples), ); evaluator.register( "http://www.w3.org/ns/rdftest#TestNQuadsNegativeSyntax", |t| evaluate_negative_dataset_syntax_test(t, DatasetFormat::NQuads), ); evaluator.register( "http://www.w3.org/ns/rdftest#TestTurtleNegativeSyntax", |t| evaluate_negative_graph_syntax_test(t, GraphFormat::Turtle), ); evaluator.register("http://www.w3.org/ns/rdftest#TestTrigNegativeSyntax", |t| { evaluate_negative_dataset_syntax_test(t, DatasetFormat::TriG) }); evaluator.register("http://www.w3.org/ns/rdftest#TestXMLNegativeSyntax", |t| { evaluate_negative_graph_syntax_test(t, GraphFormat::RdfXml) }); evaluator.register("http://www.w3.org/ns/rdftest#TestTurtleEval", |t| { evaluate_graph_eval_test(t, GraphFormat::Turtle) }); evaluator.register("http://www.w3.org/ns/rdftest#TestTrigEval", |t| { evaluate_dataset_eval_test(t, DatasetFormat::TriG) }); evaluator.register("http://www.w3.org/ns/rdftest#TestXMLEval", |t| { evaluate_graph_eval_test(t, GraphFormat::RdfXml) }); evaluator.register("http://www.w3.org/ns/rdftest#TestTurtleNegativeEval", |t| { evaluate_negative_graph_syntax_test(t, GraphFormat::Turtle) }); evaluator.register("http://www.w3.org/ns/rdftest#TestTrigNegativeEval", |t| { evaluate_negative_dataset_syntax_test(t, DatasetFormat::TriG) }); } fn evaluate_positive_graph_syntax_test(test: &Test, format: GraphFormat) -> Result<()> { let action = test .action .as_deref() .ok_or_else(|| anyhow!("No action found for test {test}"))?; load_graph(action, format).map_err(|e| anyhow!("Parse error: {e}"))?; Ok(()) } fn evaluate_positive_dataset_syntax_test(test: &Test, format: DatasetFormat) -> Result<()> { let action = test .action .as_deref() .ok_or_else(|| anyhow!("No action found for test {test}"))?; load_dataset(action, format).map_err(|e| anyhow!("Parse error: {e}"))?; Ok(()) } fn evaluate_negative_graph_syntax_test(test: &Test, format: GraphFormat) -> Result<()> { let action = test .action .as_deref() .ok_or_else(|| anyhow!("No action found for test {test}"))?; match load_graph(action, format) { Ok(_) => bail!("File parsed without errors even if it should not"), Err(_) => Ok(()), } } fn evaluate_negative_dataset_syntax_test(test: &Test, format: DatasetFormat) -> Result<()> { let action = test .action .as_deref() .ok_or_else(|| anyhow!("No action found for test {test}"))?; match load_dataset(action, format) { Ok(_) => bail!("File parsed without errors even if it should not"), Err(_) => Ok(()), } } fn evaluate_graph_eval_test(test: &Test, format: GraphFormat) -> Result<()> { let action = test .action .as_deref() .ok_or_else(|| anyhow!("No action found for test {test}"))?; let mut actual_graph = load_graph(action, format).map_err(|e| anyhow!("Parse error on file {action}: {e}"))?; actual_graph.canonicalize(); let results = test .result .as_ref() .ok_or_else(|| anyhow!("No tests result found"))?; let mut expected_graph = load_graph(results, guess_graph_format(results)?) .map_err(|e| anyhow!("Parse error on file {results}: {e}"))?; expected_graph.canonicalize(); if expected_graph == actual_graph { Ok(()) } else { bail!( "The two files are not isomorphic. Diff:\n{}", graph_diff(&expected_graph, &actual_graph) ) } } fn evaluate_dataset_eval_test(test: &Test, format: DatasetFormat) -> Result<()> { let action = test .action .as_deref() .ok_or_else(|| anyhow!("No action found for test {test}"))?; let mut actual_dataset = load_dataset(action, format).map_err(|e| anyhow!("Parse error on file {action}: {e}"))?; actual_dataset.canonicalize(); let results = test .result .as_ref() .ok_or_else(|| anyhow!("No tests result found"))?; let mut expected_dataset = load_dataset(results, guess_dataset_format(results)?) .map_err(|e| anyhow!("Parse error on file {results}: {e}"))?; expected_dataset.canonicalize(); if expected_dataset == actual_dataset { Ok(()) } else { bail!( "The two files are not isomorphic. Diff:\n{}", dataset_diff(&expected_dataset, &actual_dataset) ) } } oxigraph-0.3.22/testsuite/src/report.rs000066400000000000000000000117701453236674100201410ustar00rootroot00000000000000use anyhow::Result; use oxigraph::model::{Dataset, Graph, NamedNode}; use std::fmt::Write; use text_diff::{diff, Difference}; use time::format_description::well_known::Rfc3339; use time::OffsetDateTime; #[derive(Debug)] pub struct TestResult { pub test: NamedNode, pub outcome: Result<()>, pub date: OffsetDateTime, } pub(super) fn dataset_diff(expected: &Dataset, actual: &Dataset) -> String { format_diff( &normalize_dataset_text(expected), &normalize_dataset_text(actual), "quads", ) } fn normalize_dataset_text(store: &Dataset) -> String { let mut quads: Vec<_> = store.iter().map(|q| q.to_string()).collect(); quads.sort(); quads.join("\n") } pub(super) fn graph_diff(expected: &Graph, actual: &Graph) -> String { format_diff( &normalize_graph_text(expected), &normalize_graph_text(actual), "triples", ) } fn normalize_graph_text(store: &Graph) -> String { let mut triples: Vec<_> = store.iter().map(|q| q.to_string()).collect(); triples.sort(); triples.join("\n") } pub(super) fn format_diff(expected: &str, actual: &str, kind: &str) -> String { let (_, changeset) = diff(expected, actual, "\n"); let mut ret = String::new(); writeln!( &mut ret, "Note: missing {kind} in yellow and extra {kind} in blue" ) .unwrap(); for seq in changeset { match seq { Difference::Same(x) => { writeln!(&mut ret, "{x}").unwrap(); } Difference::Add(x) => { writeln!(&mut ret, "\x1B[94m{x}\x1B[0m").unwrap(); } Difference::Rem(x) => { writeln!(&mut ret, "\x1B[93m{x}\x1B[0m").unwrap(); } } } ret } #[allow(unused_must_use)] pub fn build_report(results: impl IntoIterator) -> String { let mut buffer = String::new(); writeln!(&mut buffer, "@prefix dc: ."); writeln!( &mut buffer, "@prefix doap: ." ); writeln!(&mut buffer, "@prefix earl: ."); writeln!(&mut buffer, "@prefix foaf: ."); writeln!( &mut buffer, "@prefix rdf: ." ); writeln!( &mut buffer, "@prefix xsd: ." ); writeln!(&mut buffer); writeln!(&mut buffer, "<> foaf:primaryTopic ;"); writeln!( &mut buffer, "\tdc:issued \"{}\"^^xsd:dateTime ;", OffsetDateTime::now_utc().format(&Rfc3339).unwrap() ); writeln!( &mut buffer, "\tfoaf:maker ." ); writeln!(&mut buffer); writeln!( &mut buffer, " a doap:Project, earl:TestSubject, earl:Software ;" ); writeln!(&mut buffer, "\tdoap:name \"Oxigraph\" ;"); writeln!(&mut buffer, "\tdoap:release ["); writeln!( &mut buffer, "\t\tdoap:name \"Oxigraph {}\";", env!("CARGO_PKG_VERSION") ); writeln!( &mut buffer, "\t\tdoap:revision \"{}\" ;", env!("CARGO_PKG_VERSION") ); writeln!(&mut buffer, "\t] ;"); writeln!( &mut buffer, "\tdoap:developer ;" ); writeln!(&mut buffer, "\tdoap:homepage ;"); writeln!( &mut buffer, "\tdoap:description \"Oxigraph is an embedded triple store.\"@en ;" ); writeln!(&mut buffer, "\tdoap:programming-language \"Rust\" ."); writeln!(&mut buffer); writeln!( &mut buffer, " a foaf:Person, earl:Assertor ;" ); writeln!(&mut buffer, "\tfoaf:name \"Thomas Tanon\"; "); writeln!( &mut buffer, "\tfoaf:homepage ." ); writeln!(&mut buffer); for result in results { writeln!(&mut buffer); writeln!(&mut buffer, "["); writeln!(&mut buffer, "\ta earl:Assertion ;"); writeln!( &mut buffer, "\tearl:assertedBy ;" ); writeln!(&mut buffer, "\tearl:subject ;"); writeln!(&mut buffer, "\tearl:test {} ;", result.test); writeln!(&mut buffer, "\tearl:result ["); writeln!(&mut buffer, "\t\ta earl:TestResult ;"); writeln!( &mut buffer, "\t\tearl:outcome earl:{} ;", if result.outcome.is_ok() { "passed" } else { "failed" } ); writeln!( &mut buffer, "\t\tdc:date \"{}\"^^xsd:dateTime", result.date.format(&Rfc3339).unwrap() ); writeln!(&mut buffer, "\t] ;"); writeln!(&mut buffer, "\tearl:mode earl:automatic"); writeln!(&mut buffer, "] ."); } buffer } oxigraph-0.3.22/testsuite/src/sparql_evaluator.rs000066400000000000000000000651741453236674100222210ustar00rootroot00000000000000use crate::evaluator::TestEvaluator; use crate::files::*; use crate::manifest::*; use crate::report::{dataset_diff, format_diff}; use crate::vocab::*; use anyhow::{anyhow, bail, Result}; use oxigraph::model::vocab::*; use oxigraph::model::*; use oxigraph::sparql::*; use oxigraph::store::Store; use std::collections::HashMap; use std::fmt::Write; use std::io::{self, Cursor}; use std::str::FromStr; use std::sync::Arc; pub fn register_sparql_tests(evaluator: &mut TestEvaluator) { evaluator.register( "http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#PositiveSyntaxTest", evaluate_positive_syntax_test, ); evaluator.register( "http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#PositiveSyntaxTest11", evaluate_positive_syntax_test, ); evaluator.register( "http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#NegativeSyntaxTest", evaluate_negative_syntax_test, ); evaluator.register( "http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#NegativeSyntaxTest11", evaluate_negative_syntax_test, ); evaluator.register( "http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#QueryEvaluationTest", evaluate_evaluation_test, ); evaluator.register( "http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#PositiveUpdateSyntaxTest11", evaluate_positive_update_syntax_test, ); evaluator.register( "http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#NegativeUpdateSyntaxTest11", evaluate_negative_update_syntax_test, ); evaluator.register( "http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#UpdateEvaluationTest", evaluate_update_evaluation_test, ); evaluator.register( "https://github.com/oxigraph/oxigraph/tests#PositiveJsonResultsSyntaxTest", evaluate_positive_json_result_syntax_test, ); evaluator.register( "https://github.com/oxigraph/oxigraph/tests#NegativeJsonResultsSyntaxTest", evaluate_negative_json_result_syntax_test, ); evaluator.register( "https://github.com/oxigraph/oxigraph/tests#PositiveXmlResultsSyntaxTest", evaluate_positive_xml_result_syntax_test, ); evaluator.register( "https://github.com/oxigraph/oxigraph/tests#NegativeXmlResultsSyntaxTest", evaluate_negative_xml_result_syntax_test, ); evaluator.register( "https://github.com/oxigraph/oxigraph/tests#NegativeTsvResultsSyntaxTest", evaluate_negative_tsv_result_syntax_test, ); } fn evaluate_positive_syntax_test(test: &Test) -> Result<()> { let query_file = test .action .as_deref() .ok_or_else(|| anyhow!("No action found for test {test}"))?; let query = Query::parse(&read_file_to_string(query_file)?, Some(query_file)) .map_err(|e| anyhow!("Not able to parse {test} with error: {e}"))?; Query::parse(&query.to_string(), None) .map_err(|e| anyhow!("Failure to deserialize \"{query}\" of {test} with error: {e}"))?; Ok(()) } fn evaluate_negative_syntax_test(test: &Test) -> Result<()> { let query_file = test .action .as_deref() .ok_or_else(|| anyhow!("No action found for test {test}"))?; match Query::parse(&read_file_to_string(query_file)?, Some(query_file)) { Ok(result) => { bail!("Oxigraph parses even if it should not {test}. The output tree is: {result}") } Err(_) => Ok(()), } } fn evaluate_positive_json_result_syntax_test(test: &Test) -> Result<()> { result_syntax_check(test, QueryResultsFormat::Json) } fn evaluate_negative_json_result_syntax_test(test: &Test) -> Result<()> { if result_syntax_check(test, QueryResultsFormat::Json).is_ok() { bail!("Oxigraph parses even if it should not {test}.") } Ok(()) } fn evaluate_positive_xml_result_syntax_test(test: &Test) -> Result<()> { result_syntax_check(test, QueryResultsFormat::Xml) } fn evaluate_negative_xml_result_syntax_test(test: &Test) -> Result<()> { if result_syntax_check(test, QueryResultsFormat::Xml).is_ok() { bail!("Oxigraph parses even if it should not {test}.") } Ok(()) } fn evaluate_negative_tsv_result_syntax_test(test: &Test) -> Result<()> { if result_syntax_check(test, QueryResultsFormat::Tsv).is_ok() { bail!("Oxigraph parses even if it should not {test}.") } Ok(()) } fn result_syntax_check(test: &Test, format: QueryResultsFormat) -> Result<()> { let action_file = test .action .as_deref() .ok_or_else(|| anyhow!("No action found for test {test}"))?; let actual_results = StaticQueryResults::from_query_results( QueryResults::read(Cursor::new(read_file_to_string(action_file)?), format)?, true, )?; if let Some(result_file) = test.result.as_deref() { let expected_results = StaticQueryResults::from_query_results( QueryResults::read(Cursor::new(read_file_to_string(result_file)?), format)?, true, )?; if !are_query_results_isomorphic(&expected_results, &actual_results) { bail!( "Failure on {test}.\n{}\n", results_diff(expected_results, actual_results), ); } } Ok(()) } fn evaluate_evaluation_test(test: &Test) -> Result<()> { let store = Store::new()?; if let Some(data) = &test.data { load_dataset_to_store(data, &store)?; } for (name, value) in &test.graph_data { load_graph_to_store(value, &store, name)?; } let query_file = test .query .as_deref() .ok_or_else(|| anyhow!("No action found for test {test}"))?; let options = QueryOptions::default() .with_service_handler(StaticServiceHandler::new(&test.service_data)?); let query = Query::parse(&read_file_to_string(query_file)?, Some(query_file)) .map_err(|e| anyhow!("Failure to parse query of {test} with error: {e}"))?; // We check parsing roundtrip Query::parse(&query.to_string(), None) .map_err(|e| anyhow!("Failure to deserialize \"{query}\" of {test} with error: {e}"))?; // FROM and FROM NAMED support. We make sure the data is in the store if !query.dataset().is_default_dataset() { for graph_name in query.dataset().default_graph_graphs().unwrap_or(&[]) { if let GraphName::NamedNode(graph_name) = graph_name { load_graph_to_store(graph_name.as_str(), &store, graph_name.as_ref())?; } else { bail!("Invalid FROM in query {query} for test {test}"); } } for graph_name in query.dataset().available_named_graphs().unwrap_or(&[]) { if let NamedOrBlankNode::NamedNode(graph_name) = graph_name { load_graph_to_store(graph_name.as_str(), &store, graph_name.as_ref())?; } else { bail!("Invalid FROM NAMED in query {query} for test {test}"); } } } let expected_results = load_sparql_query_result(test.result.as_ref().unwrap()) .map_err(|e| anyhow!("Error constructing expected graph for {test}: {e}"))?; let with_order = if let StaticQueryResults::Solutions { ordered, .. } = &expected_results { *ordered } else { false }; for with_query_optimizer in [true, false] { let mut options = options.clone(); if !with_query_optimizer { options = options.without_optimizations(); } let actual_results = store .query_opt(query.clone(), options) .map_err(|e| anyhow!("Failure to execute query of {test} with error: {e}"))?; let actual_results = StaticQueryResults::from_query_results(actual_results, with_order)?; if !are_query_results_isomorphic(&expected_results, &actual_results) { bail!( "Failure on {test}.\n{}\nParsed query:\n{}\nData:\n{store}\n", results_diff(expected_results, actual_results), Query::parse(&read_file_to_string(query_file)?, Some(query_file)).unwrap() ); } } Ok(()) } fn evaluate_positive_update_syntax_test(test: &Test) -> Result<()> { let update_file = test .action .as_deref() .ok_or_else(|| anyhow!("No action found for test {test}"))?; let update = Update::parse(&read_file_to_string(update_file)?, Some(update_file)) .map_err(|e| anyhow!("Not able to parse {test} with error: {e}"))?; Update::parse(&update.to_string(), None) .map_err(|e| anyhow!("Failure to deserialize \"{update}\" of {test} with error: {e}"))?; Ok(()) } fn evaluate_negative_update_syntax_test(test: &Test) -> Result<()> { let update_file = test .action .as_deref() .ok_or_else(|| anyhow!("No action found for test {test}"))?; match Update::parse(&read_file_to_string(update_file)?, Some(update_file)) { Ok(result) => { bail!("Oxigraph parses even if it should not {test}. The output tree is: {result}") } Err(_) => Ok(()), } } fn evaluate_update_evaluation_test(test: &Test) -> Result<()> { let store = Store::new()?; if let Some(data) = &test.data { load_dataset_to_store(data, &store)?; } for (name, value) in &test.graph_data { load_graph_to_store(value, &store, name)?; } let result_store = Store::new()?; if let Some(data) = &test.result { load_dataset_to_store(data, &result_store)?; } for (name, value) in &test.result_graph_data { load_graph_to_store(value, &result_store, name)?; } let update_file = test .update .as_deref() .ok_or_else(|| anyhow!("No action found for test {test}"))?; let update = Update::parse(&read_file_to_string(update_file)?, Some(update_file)) .map_err(|e| anyhow!("Failure to parse update of {test} with error: {e}"))?; // We check parsing roundtrip Update::parse(&update.to_string(), None) .map_err(|e| anyhow!("Failure to deserialize \"{update}\" of {test} with error: {e}"))?; store .update(update) .map_err(|e| anyhow!("Failure to execute update of {test} with error: {e}"))?; let mut store_dataset: Dataset = store.iter().collect::>()?; store_dataset.canonicalize(); let mut result_store_dataset: Dataset = result_store.iter().collect::>()?; result_store_dataset.canonicalize(); if store_dataset == result_store_dataset { Ok(()) } else { bail!( "Failure on {test}.\nDiff:\n{}\nParsed update:\n{}\n", dataset_diff(&result_store_dataset, &store_dataset), Update::parse(&read_file_to_string(update_file)?, Some(update_file)).unwrap(), ) } } fn load_sparql_query_result(url: &str) -> Result { if let Some(format) = url .rsplit_once('.') .and_then(|(_, extension)| QueryResultsFormat::from_extension(extension)) { StaticQueryResults::from_query_results(QueryResults::read(read_file(url)?, format)?, false) } else { StaticQueryResults::from_graph(&load_graph(url, guess_graph_format(url)?)?) } } #[derive(Clone)] struct StaticServiceHandler { services: Arc>, } impl StaticServiceHandler { fn new(services: &[(String, String)]) -> Result { Ok(Self { services: Arc::new( services .iter() .map(|(name, data)| { let name = NamedNode::new(name)?; let store = Store::new()?; load_dataset_to_store(data, &store)?; Ok((name, store)) }) .collect::>()?, ), }) } } impl ServiceHandler for StaticServiceHandler { type Error = EvaluationError; fn handle( &self, service_name: NamedNode, query: Query, ) -> std::result::Result { self.services .get(&service_name) .ok_or_else(|| { io::Error::new( io::ErrorKind::InvalidInput, format!("Service {service_name} not found"), ) })? .query_opt( query, QueryOptions::default().with_service_handler(self.clone()), ) } } fn to_graph(result: QueryResults, with_order: bool) -> Result { Ok(match result { QueryResults::Graph(graph) => graph.collect::>()?, QueryResults::Boolean(value) => { let mut graph = Graph::new(); let result_set = BlankNode::default(); graph.insert(TripleRef::new(&result_set, rdf::TYPE, rs::RESULT_SET)); graph.insert(TripleRef::new( &result_set, rs::BOOLEAN, &Literal::from(value), )); graph } QueryResults::Solutions(solutions) => { let mut graph = Graph::new(); let result_set = BlankNode::default(); graph.insert(TripleRef::new(&result_set, rdf::TYPE, rs::RESULT_SET)); for variable in solutions.variables() { graph.insert(TripleRef::new( &result_set, rs::RESULT_VARIABLE, LiteralRef::new_simple_literal(variable.as_str()), )); } for (i, solution) in solutions.enumerate() { let solution = solution?; let solution_id = BlankNode::default(); graph.insert(TripleRef::new(&result_set, rs::SOLUTION, &solution_id)); for (variable, value) in solution.iter() { let binding = BlankNode::default(); graph.insert(TripleRef::new(&solution_id, rs::BINDING, &binding)); graph.insert(TripleRef::new(&binding, rs::VALUE, value)); graph.insert(TripleRef::new( &binding, rs::VARIABLE, LiteralRef::new_simple_literal(variable.as_str()), )); } if with_order { graph.insert(TripleRef::new( &solution_id, rs::INDEX, &Literal::from((i + 1) as i128), )); } } graph } }) } fn are_query_results_isomorphic( expected: &StaticQueryResults, actual: &StaticQueryResults, ) -> bool { match (expected, actual) { ( StaticQueryResults::Solutions { variables: expected_variables, solutions: expected_solutions, ordered, }, StaticQueryResults::Solutions { variables: actual_variables, solutions: actual_solutions, .. }, ) => { expected_variables == actual_variables && expected_solutions.len() == actual_solutions.len() && if *ordered { expected_solutions.iter().zip(actual_solutions).all( |(expected_solution, actual_solution)| { compare_solutions(expected_solution, actual_solution) }, ) } else { expected_solutions.iter().all(|expected_solution| { actual_solutions.iter().any(|actual_solution| { compare_solutions(expected_solution, actual_solution) }) }) } } (StaticQueryResults::Boolean(expected), StaticQueryResults::Boolean(actual)) => { expected == actual } (StaticQueryResults::Graph(expected), StaticQueryResults::Graph(actual)) => { expected == actual } _ => false, } } fn compare_solutions(expected: &[(Variable, Term)], actual: &[(Variable, Term)]) -> bool { let mut bnode_map = HashMap::new(); expected.len() == actual.len() && expected.iter().zip(actual).all( move |((expected_variable, expected_value), (actual_variable, actual_value))| { expected_variable == actual_variable && compare_terms( expected_value.as_ref(), actual_value.as_ref(), &mut bnode_map, ) }, ) } fn compare_terms<'a>( expected: TermRef<'a>, actual: TermRef<'a>, bnode_map: &mut HashMap, BlankNodeRef<'a>>, ) -> bool { match (expected, actual) { (TermRef::BlankNode(expected), TermRef::BlankNode(actual)) => { expected == *bnode_map.entry(actual).or_insert(expected) } (TermRef::Triple(expected), TermRef::Triple(actual)) => { compare_terms( expected.subject.as_ref().into(), actual.subject.as_ref().into(), bnode_map, ) && compare_terms( expected.predicate.as_ref().into(), actual.predicate.as_ref().into(), bnode_map, ) && compare_terms(expected.object.as_ref(), actual.object.as_ref(), bnode_map) } (expected, actual) => expected == actual, } } #[allow(clippy::large_enum_variant)] enum StaticQueryResults { Graph(Graph), Solutions { variables: Vec, solutions: Vec>, ordered: bool, }, Boolean(bool), } impl StaticQueryResults { fn from_query_results(results: QueryResults, with_order: bool) -> Result { Self::from_graph(&to_graph(results, with_order)?) } fn from_graph(graph: &Graph) -> Result { // Hack to normalize literals let store = Store::new()?; for t in graph.iter() { store .insert(t.in_graph(GraphNameRef::DefaultGraph)) .unwrap(); } let mut graph: Graph = store.iter().map(|q| Triple::from(q.unwrap())).collect(); if let Some(result_set) = graph.subject_for_predicate_object(rdf::TYPE, rs::RESULT_SET) { if let Some(bool) = graph.object_for_subject_predicate(result_set, rs::BOOLEAN) { // Boolean query Ok(Self::Boolean(bool == Literal::from(true).as_ref().into())) } else { // Regular query let mut variables: Vec = graph .objects_for_subject_predicate(result_set, rs::RESULT_VARIABLE) .map(|object| { if let TermRef::Literal(l) = object { Ok(Variable::new_unchecked(l.value())) } else { bail!("Invalid rs:resultVariable: {object}") } }) .collect::>>()?; variables.sort(); let mut solutions = graph .objects_for_subject_predicate(result_set, rs::SOLUTION) .map(|object| { if let TermRef::BlankNode(solution) = object { let mut bindings = graph .objects_for_subject_predicate(solution, rs::BINDING) .map(|object| { if let TermRef::BlankNode(binding) = object { if let (Some(TermRef::Literal(variable)), Some(value)) = ( graph.object_for_subject_predicate( binding, rs::VARIABLE, ), graph.object_for_subject_predicate(binding, rs::VALUE), ) { Ok(( Variable::new_unchecked(variable.value()), value.into_owned(), )) } else { bail!("Invalid rs:binding: {binding}") } } else { bail!("Invalid rs:binding: {object}") } }) .collect::>>()?; bindings.sort_by(|(a, _), (b, _)| a.cmp(b)); let index = graph .object_for_subject_predicate(solution, rs::INDEX) .map(|object| { if let TermRef::Literal(l) = object { Ok(u64::from_str(l.value())?) } else { bail!("Invalid rs:index: {object}") } }) .transpose()?; Ok((bindings, index)) } else { bail!("Invalid rs:solution: {object}") } }) .collect::>>()?; solutions.sort_by(|(_, index_a), (_, index_b)| index_a.cmp(index_b)); let ordered = solutions.iter().all(|(_, index)| index.is_some()); Ok(Self::Solutions { variables, solutions: solutions .into_iter() .map(|(solution, _)| solution) .collect(), ordered, }) } } else { graph.canonicalize(); Ok(Self::Graph(graph)) } } } fn results_diff(expected: StaticQueryResults, actual: StaticQueryResults) -> String { match expected { StaticQueryResults::Solutions { variables: mut expected_variables, solutions: expected_solutions, ordered, } => match actual { StaticQueryResults::Solutions { variables: mut actual_variables, solutions: actual_solutions, .. } => { let mut out = String::new(); expected_variables.sort_unstable(); actual_variables.sort_unstable(); if expected_variables != actual_variables { write!( &mut out, "Variables diff:\n{}", format_diff( &expected_variables .iter() .map(ToString::to_string) .collect::>() .join("\n"), &actual_variables .iter() .map(ToString::to_string) .collect::>() .join("\n"), "variables", ) ) .unwrap(); } write!( &mut out, "Solutions diff:\n{}", format_diff( &solutions_to_string(expected_solutions, ordered), &solutions_to_string(actual_solutions, ordered), "solutions", ) ) .unwrap(); out } StaticQueryResults::Boolean(actual) => { format!("Expecting solutions but found the boolean {actual}") } StaticQueryResults::Graph(actual) => { format!("Expecting solutions but found the graph:\n{actual}") } }, StaticQueryResults::Graph(expected) => match actual { StaticQueryResults::Solutions { .. } => "Expecting a graph but found solutions".into(), StaticQueryResults::Boolean(actual) => { format!("Expecting a graph but found the boolean {actual}") } StaticQueryResults::Graph(actual) => { let expected = expected .into_iter() .map(|t| t.in_graph(GraphNameRef::DefaultGraph)) .collect(); let actual = actual .into_iter() .map(|t| t.in_graph(GraphNameRef::DefaultGraph)) .collect(); dataset_diff(&expected, &actual) } }, StaticQueryResults::Boolean(expected) => match actual { StaticQueryResults::Solutions { .. } => { "Expecting a boolean but found solutions".into() } StaticQueryResults::Boolean(actual) => { format!("Expecting {expected} but found {actual}") } StaticQueryResults::Graph(actual) => { format!("Expecting solutions but found the graph:\n{actual}") } }, } } fn solutions_to_string(solutions: Vec>, ordered: bool) -> String { let mut lines = solutions .into_iter() .map(|mut s| { let mut out = String::new(); write!(&mut out, "{{").unwrap(); s.sort_unstable_by(|(v1, _), (v2, _)| v1.cmp(v2)); for (variable, value) in s { write!(&mut out, "{variable} = {value} ").unwrap(); } write!(&mut out, "}}").unwrap(); out }) .collect::>(); if !ordered { lines.sort_unstable(); } lines.join("\n") } fn load_graph_to_store<'a>( url: &str, store: &Store, to_graph_name: impl Into>, ) -> Result<()> { store.load_graph( read_file(url)?, guess_graph_format(url)?, to_graph_name, Some(url), )?; Ok(()) } fn load_dataset_to_store(url: &str, store: &Store) -> Result<()> { if let Ok(format) = guess_dataset_format(url) { store.load_dataset(read_file(url)?, format, Some(url)) } else { store.load_graph( read_file(url)?, guess_graph_format(url)?, GraphNameRef::DefaultGraph, Some(url), ) }?; Ok(()) } oxigraph-0.3.22/testsuite/src/vocab.rs000066400000000000000000000075461453236674100177260ustar00rootroot00000000000000pub mod rs { use oxigraph::model::NamedNodeRef; pub const RESULT_SET: NamedNodeRef<'_> = NamedNodeRef::new_unchecked( "http://www.w3.org/2001/sw/DataAccess/tests/result-set#ResultSet", ); pub const RESULT_VARIABLE: NamedNodeRef<'_> = NamedNodeRef::new_unchecked( "http://www.w3.org/2001/sw/DataAccess/tests/result-set#resultVariable", ); pub const SOLUTION: NamedNodeRef<'_> = NamedNodeRef::new_unchecked( "http://www.w3.org/2001/sw/DataAccess/tests/result-set#solution", ); pub const BINDING: NamedNodeRef<'_> = NamedNodeRef::new_unchecked( "http://www.w3.org/2001/sw/DataAccess/tests/result-set#binding", ); pub const VALUE: NamedNodeRef<'_> = NamedNodeRef::new_unchecked("http://www.w3.org/2001/sw/DataAccess/tests/result-set#value"); pub const VARIABLE: NamedNodeRef<'_> = NamedNodeRef::new_unchecked( "http://www.w3.org/2001/sw/DataAccess/tests/result-set#variable", ); pub const INDEX: NamedNodeRef<'_> = NamedNodeRef::new_unchecked("http://www.w3.org/2001/sw/DataAccess/tests/result-set#index"); pub const BOOLEAN: NamedNodeRef<'_> = NamedNodeRef::new_unchecked( "http://www.w3.org/2001/sw/DataAccess/tests/result-set#boolean", ); } pub mod mf { use oxigraph::model::NamedNodeRef; pub const INCLUDE: NamedNodeRef<'_> = NamedNodeRef::new_unchecked( "http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#include", ); pub const ENTRIES: NamedNodeRef<'_> = NamedNodeRef::new_unchecked( "http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#entries", ); pub const MANIFEST: NamedNodeRef<'_> = NamedNodeRef::new_unchecked( "http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#Manifest", ); pub const NAME: NamedNodeRef<'_> = NamedNodeRef::new_unchecked( "http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#name", ); pub const ACTION: NamedNodeRef<'_> = NamedNodeRef::new_unchecked( "http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#action", ); pub const RESULT: NamedNodeRef<'_> = NamedNodeRef::new_unchecked( "http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#result", ); } pub mod rdft { use oxigraph::model::NamedNodeRef; pub const APPROVAL: NamedNodeRef<'_> = NamedNodeRef::new_unchecked("http://www.w3.org/ns/rdftest#approval"); pub const REJECTED: NamedNodeRef<'_> = NamedNodeRef::new_unchecked("http://www.w3.org/ns/rdftest#Rejected"); } pub mod qt { use oxigraph::model::NamedNodeRef; pub const QUERY: NamedNodeRef<'_> = NamedNodeRef::new_unchecked("http://www.w3.org/2001/sw/DataAccess/tests/test-query#query"); pub const DATA: NamedNodeRef<'_> = NamedNodeRef::new_unchecked("http://www.w3.org/2001/sw/DataAccess/tests/test-query#data"); pub const GRAPH_DATA: NamedNodeRef<'_> = NamedNodeRef::new_unchecked( "http://www.w3.org/2001/sw/DataAccess/tests/test-query#graphData", ); pub const SERVICE_DATA: NamedNodeRef<'_> = NamedNodeRef::new_unchecked( "http://www.w3.org/2001/sw/DataAccess/tests/test-query#serviceData", ); pub const ENDPOINT: NamedNodeRef<'_> = NamedNodeRef::new_unchecked( "http://www.w3.org/2001/sw/DataAccess/tests/test-query#endpoint", ); } pub mod ut { use oxigraph::model::NamedNodeRef; pub const DATA: NamedNodeRef<'_> = NamedNodeRef::new_unchecked("http://www.w3.org/2009/sparql/tests/test-update#data"); pub const GRAPH_DATA: NamedNodeRef<'_> = NamedNodeRef::new_unchecked("http://www.w3.org/2009/sparql/tests/test-update#graphData"); pub const GRAPH: NamedNodeRef<'_> = NamedNodeRef::new_unchecked("http://www.w3.org/2009/sparql/tests/test-update#graph"); pub const REQUEST: NamedNodeRef<'_> = NamedNodeRef::new_unchecked("http://www.w3.org/2009/sparql/tests/test-update#request"); } oxigraph-0.3.22/testsuite/tests/000077500000000000000000000000001453236674100166255ustar00rootroot00000000000000oxigraph-0.3.22/testsuite/tests/oxigraph.rs000066400000000000000000000021551453236674100210170ustar00rootroot00000000000000use anyhow::Result; use oxigraph_testsuite::evaluator::TestEvaluator; use oxigraph_testsuite::manifest::TestManifest; use oxigraph_testsuite::sparql_evaluator::register_sparql_tests; fn run_testsuite(manifest_urls: Vec<&str>) -> Result<()> { let mut evaluator = TestEvaluator::default(); register_sparql_tests(&mut evaluator); let manifest = TestManifest::new(manifest_urls); let results = evaluator.evaluate(manifest)?; let mut errors = Vec::default(); for result in results { if let Err(error) = &result.outcome { errors.push(format!("{}: failed with error {}", result.test, error)) } } assert!( errors.is_empty(), "{} failing tests:\n{}\n", errors.len(), errors.join("\n") ); Ok(()) } #[test] fn oxigraph_sparql_testsuite() -> Result<()> { run_testsuite(vec![ "https://github.com/oxigraph/oxigraph/tests/sparql/manifest.ttl", ]) } #[test] fn oxigraph_sparql_results_testsuite() -> Result<()> { run_testsuite(vec![ "https://github.com/oxigraph/oxigraph/tests/sparql-results/manifest.ttl", ]) } oxigraph-0.3.22/testsuite/tests/parser.rs000066400000000000000000000043761453236674100205010ustar00rootroot00000000000000use anyhow::Result; use oxigraph_testsuite::evaluator::TestEvaluator; use oxigraph_testsuite::manifest::TestManifest; use oxigraph_testsuite::parser_evaluator::register_parser_tests; fn run_testsuite(manifest_url: &str) -> Result<()> { let mut evaluator = TestEvaluator::default(); register_parser_tests(&mut evaluator); let manifest = TestManifest::new(vec![manifest_url]); let results = evaluator.evaluate(manifest)?; let mut errors = Vec::default(); for result in results { if let Err(error) = &result.outcome { errors.push(format!("{}: failed with error {}", result.test, error)) } } assert!( errors.is_empty(), "{} failing tests:\n{}\n", errors.len(), errors.join("\n") ); Ok(()) } #[test] fn ntriples_w3c_testsuite() -> Result<()> { run_testsuite("http://w3c.github.io/rdf-tests/ntriples/manifest.ttl") } #[test] fn nquads_w3c_testsuite() -> Result<()> { run_testsuite("http://w3c.github.io/rdf-tests/nquads/manifest.ttl") } #[cfg(not(target_os = "windows"))] // Tests don't like git auto "\r\n" on Windows #[test] fn turtle_w3c_testsuite() -> Result<()> { run_testsuite("http://w3c.github.io/rdf-tests/turtle/manifest.ttl") } #[cfg(not(target_os = "windows"))] // Tests don't like git auto "\r\n" on Windows #[test] fn trig_w3c_testsuite() -> Result<()> { run_testsuite("http://w3c.github.io/rdf-tests/trig/manifest.ttl") } #[test] fn rdf_xml_w3c_testsuite() -> Result<()> { run_testsuite("http://www.w3.org/2013/RDFXMLTests/manifest.ttl") } #[test] fn ntriples_star_w3c_testsuite() -> Result<()> { run_testsuite("https://w3c.github.io/rdf-star/tests/nt/syntax/manifest.ttl") } #[test] fn turtle_star_syntax_w3c_testsuite() -> Result<()> { run_testsuite("https://w3c.github.io/rdf-star/tests/turtle/syntax/manifest.ttl") } #[test] fn turtle_star_eval_w3c_testsuite() -> Result<()> { run_testsuite("https://w3c.github.io/rdf-star/tests/turtle/eval/manifest.ttl") } #[test] fn trig_star_syntax_w3c_testsuite() -> Result<()> { run_testsuite("https://w3c.github.io/rdf-star/tests/trig/syntax/manifest.ttl") } #[test] fn trig_star_eval_w3c_testsuite() -> Result<()> { run_testsuite("https://w3c.github.io/rdf-star/tests/trig/eval/manifest.ttl") } oxigraph-0.3.22/testsuite/tests/sparql.rs000066400000000000000000000140411453236674100204750ustar00rootroot00000000000000use anyhow::Result; use oxigraph_testsuite::evaluator::TestEvaluator; use oxigraph_testsuite::manifest::TestManifest; use oxigraph_testsuite::sparql_evaluator::register_sparql_tests; fn run_testsuite(manifest_url: &str, ignored_tests: &[&str]) -> Result<()> { let mut evaluator = TestEvaluator::default(); register_sparql_tests(&mut evaluator); let manifest = TestManifest::new(vec![manifest_url]); let results = evaluator.evaluate(manifest)?; let mut errors = Vec::default(); for result in results { if let Err(error) = &result.outcome { if !ignored_tests.contains(&result.test.as_str()) { errors.push(format!("{}: failed with error {}", result.test, error)) } } } assert!( errors.is_empty(), "{} failing tests:\n{}\n", errors.len(), errors.join("\n") ); Ok(()) } #[test] fn sparql10_w3c_query_syntax_testsuite() -> Result<()> { run_testsuite( "https://w3c.github.io/rdf-tests/sparql/sparql10/manifest-syntax.ttl", &[ "http://www.w3.org/2001/sw/DataAccess/tests/data-r2/syntax-sparql3/manifest#syn-bad-26", // tokenizer ], ) } #[test] fn sparql10_w3c_query_evaluation_testsuite() -> Result<()> { run_testsuite("https://w3c.github.io/rdf-tests/sparql/sparql10/manifest-evaluation.ttl", &[ //Multiple writing of the same xsd:integer. Our system does strong normalization. "http://www.w3.org/2001/sw/DataAccess/tests/data-r2/distinct/manifest#distinct-1", "http://www.w3.org/2001/sw/DataAccess/tests/data-r2/distinct/manifest#distinct-9", "http://www.w3.org/2001/sw/DataAccess/tests/data-r2/expr-builtin/manifest#dawg-str-1", "http://www.w3.org/2001/sw/DataAccess/tests/data-r2/expr-builtin/manifest#dawg-str-2", "http://www.w3.org/2001/sw/DataAccess/tests/data-r2/expr-equals/manifest#eq-graph-1", "http://www.w3.org/2001/sw/DataAccess/tests/data-r2/expr-equals/manifest#eq-graph-2", "http://www.w3.org/2001/sw/DataAccess/tests/data-r2/open-world/manifest#open-eq-01", "http://www.w3.org/2001/sw/DataAccess/tests/data-r2/open-world/manifest#open-eq-04", //Multiple writing of the same xsd:double. Our system does strong normalization. "http://www.w3.org/2001/sw/DataAccess/tests/data-r2/expr-builtin/manifest#sameTerm", "http://www.w3.org/2001/sw/DataAccess/tests/data-r2/expr-builtin/manifest#sameTerm-simple", "http://www.w3.org/2001/sw/DataAccess/tests/data-r2/expr-builtin/manifest#sameTerm-eq", "http://www.w3.org/2001/sw/DataAccess/tests/data-r2/expr-builtin/manifest#sameTerm-not-eq", //Simple literal vs xsd:string. We apply RDF 1.1 "http://www.w3.org/2001/sw/DataAccess/tests/data-r2/distinct/manifest#distinct-2", "http://www.w3.org/2001/sw/DataAccess/tests/data-r2/open-world/manifest#open-eq-08", "http://www.w3.org/2001/sw/DataAccess/tests/data-r2/open-world/manifest#open-eq-10", "http://www.w3.org/2001/sw/DataAccess/tests/data-r2/open-world/manifest#open-eq-11", "http://www.w3.org/2001/sw/DataAccess/tests/data-r2/open-world/manifest#open-eq-12", //DATATYPE("foo"@en) returns rdf:langString in RDF 1.1 "http://www.w3.org/2001/sw/DataAccess/tests/data-r2/expr-builtin/manifest#dawg-datatype-2", // We use XSD 1.1 equality on dates "http://www.w3.org/2001/sw/DataAccess/tests/data-r2/open-world/manifest#date-2", // We choose to simplify first the nested group patterns in OPTIONAL "http://www.w3.org/2001/sw/DataAccess/tests/data-r2/optional-filter/manifest#dawg-optional-filter-005-not-simplified", // This test relies on naive iteration on the input file "http://www.w3.org/2001/sw/DataAccess/tests/data-r2/reduced/manifest#reduced-2" ]) } #[test] fn sparql11_query_w3c_evaluation_testsuite() -> Result<()> { run_testsuite( "https://w3c.github.io/rdf-tests/sparql/sparql11/manifest-sparql11-query.ttl", &[ //BNODE() scope is currently wrong "http://www.w3.org/2009/sparql/docs/tests/data-sparql11/functions/manifest#bnode01", //SERVICE name from a BGP "http://www.w3.org/2009/sparql/docs/tests/data-sparql11/service/manifest#service5", ], ) } #[test] fn sparql11_federation_w3c_evaluation_testsuite() -> Result<()> { run_testsuite( "https://w3c.github.io/rdf-tests/sparql/sparql11/manifest-sparql11-fed.ttl", &[ // Problem during service evaluation order "http://www.w3.org/2009/sparql/docs/tests/data-sparql11/service/manifest#service5", ], ) } #[test] fn sparql11_update_w3c_evaluation_testsuite() -> Result<()> { run_testsuite( "https://w3c.github.io/rdf-tests/sparql/sparql11/manifest-sparql11-update.ttl", &[ // We allow multiple INSERT DATA with the same blank nodes "http://www.w3.org/2009/sparql/docs/tests/data-sparql11/syntax-update-1/manifest#test_54", ], ) } #[test] fn sparql11_json_w3c_evaluation_testsuite() -> Result<()> { run_testsuite( "https://w3c.github.io/rdf-tests/sparql/sparql11/json-res/manifest.ttl", &[], ) } #[test] fn sparql11_tsv_w3c_evaluation_testsuite() -> Result<()> { run_testsuite( "https://w3c.github.io/rdf-tests/sparql/sparql11/csv-tsv-res/manifest.ttl", &[ // We do not run CSVResultFormatTest tests yet "http://www.w3.org/2009/sparql/docs/tests/data-sparql11/csv-tsv-res/manifest#csv01", "http://www.w3.org/2009/sparql/docs/tests/data-sparql11/csv-tsv-res/manifest#csv02", "http://www.w3.org/2009/sparql/docs/tests/data-sparql11/csv-tsv-res/manifest#csv03", ], ) } #[test] fn sparql_star_syntax_testsuite() -> Result<()> { run_testsuite( "https://w3c.github.io/rdf-star/tests/sparql/syntax/manifest.ttl", &[], ) } #[test] fn sparql_star_eval_testsuite() -> Result<()> { run_testsuite( "https://w3c.github.io/rdf-star/tests/sparql/eval/manifest.ttl", &[], ) } oxigraph-0.3.22/typos.toml000066400000000000000000000000461453236674100155050ustar00rootroot00000000000000[files] extend-exclude = ["**/*.svg"]